2013-06-18 39 views
6

Tôi muốn gọi đoạn mã sau trong C++, mà tôi không thể thay đổi:Làm thế nào để tránh chuyển đổi NỮA từ chuỗi liên tục để 'char *' trong C++

void getAge(char *name) 
{ 
// do something 
} 

Khi tôi gọi nó với getAge("hello");, nó có cảnh báo sau:

warning: deprecated conversion from string constant to 'char*' 

nhưng không có cảnh báo trong mã C. Sự khác nhau là gì và làm cách nào để thay đổi cuộc gọi để tránh cảnh báo trong C++?

+4

Đặt tham số hàm là 'const char *'? –

+0

không, đó là chức năng được xác định bởi người khác, không thể thay đổi – user2131316

+1

Trong trường hợp đó, hãy bỏ đối số. –

Trả lời

17

chức năng [...] không thể thay đổi

Sau đó viết một wrapper quanh chức năng và sao chép chuỗi - hoặc, nếu bạn cảm thấy may mắn (= bạn biết rằng chuỗi chiến thắng' t được sửa đổi bên trong hàm gốc), dứt khoát bỏ đi const-ness:

void getAge(char const* name) { 
    the_namespace::getAge(const_cast<char*>(name)); 
} 

Nếu bạn không chắc chắn liệu chức năng làm thay đổi các thông số của nó, sử dụng giống như sau - tuy nhiên, nếu đó là trường hợp sau đó gọi hàm bằng một chuỗi ký tự (getAge("hello")) sẽ không hợp lệ.

void getAge(char const* name) { 
    std::string buffer(name); 
    the_namespace::getAge(&buffer[0]); 
} 

Ở đây chúng tôi sao chép chuỗi vào bộ đệm có thể sửa đổi và chuyển địa chỉ đến ký tự đầu tiên của nó đến hàm ban đầu.

+0

@EricPostpischil Và những gì "sao chép chuỗi" có nghĩa là, nếu không. –

0

Bạn có thể thử getAge((char*)"hello").

+1

Chỉ khi bạn biết rằng hàm sẽ không cố sửa đổi chuỗi. Và bạn thực sự nên sử dụng C++ phôi. –

+0

Thẻ này được gắn thẻ 'C++'. –

0

Trong C++ bạn có thể viết nó như thế này, void getAge(string name) { // do something } và cũng bao gồm các tập tin tiêu đề #include<string> vì bạn đang sử dụng chuỗi tại

+0

void getAge() phương pháp không thể thay đổi – user2131316

+1

Đọc câu hỏi xin vui lòng ... – nouney

+1

@nouney, các "không thể thay đổi" thông tin không được nêu trong câu hỏi được nêu ra, nhưng chỉ trong các ý kiến. – Steed

2

Cách an toàn nhất là để sao chép chuỗi, sau đó gọi hàm C:

void getAgeSafe(const char* name) 
{ 
    std::vector<char> tmp = name? 
    std::vector<char>(name, name+1+strlen(name)) 
    :std::vector<char>(); 

    getAge(tmp.data()); 
} 

và gọi getAgeSafe từ mã C++ của bạn.

Một cách kém an toàn dựa trên mã C bao giờ sửa đổi char* name sẽ được const_cast, một lần nữa trong một "gói" chức năng:

void getAgeUnsafe(const char* name) 
{ 
    getAge(const_cast<char*>(name)); 
} 

nhưng lần này tên là đáng sợ hơn, vì là hoạt động. Nếu bạn gọi getAge với chuỗi thời gian biên dịch như "bob", nếu getAge sửa đổi đầu vào, kết quả hành vi không xác định (điều này đúng trong cả C và C++ - C++ ít nhất thì cảnh báo bạn).

+0

'c_str()' trả về 'const char *' vì vậy bạn sẽ nhận được cảnh báo tương tự. Việc chuyển '& name [0]' sẽ hoạt động. – SirGuy

+0

@GuyGreer oops, cố định. Ngay cả 'dữ liệu()' là 'const' cho' std :: string', do đó, thay vào đó xây dựng một bộ đệm của 'std :: vector '. (Tôi không chắc chắn rằng '& name [0]' được đảm bảo là null chấm dứt theo tiêu chuẩn?) – Yakk

+0

@Yakk Nó là trong C++ 11 (null chấm dứt không phải là vấn đề trước khi một trong hai - tiếp giáp của lưu trữ là). Mã hiện tại của bạn là không nhất thiết phức tạp theo ý kiến ​​của tôi; chỉ cần sử dụng hàm tạo thích hợp để khởi tạo vectơ (tất nhiên là làm cho việc kiểm tra null không thể hoặc ít nhất là khó hơn). –

Các vấn đề liên quan