вот моя проблема.
У меня есть класс, который регулярно модифицирует символ *.
Есть еще один класс, который должен уметь читать это значение. Поэтому я хочу передать char * в конструктор этого второго класса, чтобы он мог проверить значение, когда это необходимо.
Позвольте мне привести пример реализации, которую я имею для другого параметра, он имеет тип boolean:
В классе А:
bool f_valid = false; // global
m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall(&f_valid)));
В классе B:
struct handleCall
{
bool* m_dataValid;
handleCall(bool* result)
{
// saving the pointer to the boolean that I want to change
m_dataValid = result;
}
method()
{
if (smth)
{
(*m_dataValid) = false;
}
}
};
Пока все хорошо — это похоже на работу. Оба класса могут изменить и получить доступ к этому логическому значению.
Теперь мне нужно сделать то же самое с символом * (я не могу использовать строку, поэтому я думаю, что это лучший способ сохранить короткий текст, например, URL-адрес?).
Итак, вот что я написал:
ClassA:
const char* f_url = "blah blah"; // global
m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));
ClassC:
struct handleCall2
{
char ** m_url;
handleCall2(char** url)
{
// saving the pointer to the char*
m_url= url;
std::cout << (*m_url) << std::endl; // prints out url fine
}
method()
{
std::cout << (*m_url) << std::endl; // by this time the value has been changed by ClassA, and I print out some rubbish - symbols, squares, etc.
}
};
Я думаю, проблема в том, что строка изменилась, ее адрес тоже изменился? Я действительно запутался — может кто-нибудь сказать мне, что происходит, и что я должен делать в этой ситуации?
ОБНОВИТЬ:
Похоже, проблема в том, КАК я изменяю char *:
f_url = "new text"; // works fine
f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB
strcpy(m_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(
Есть ли другой способ записать значение строки в символ *?
Я не вижу никаких проблем с доступом к char *
,
Я написал пример кода, и он работал для меня. Может быть, твоя другая проблема:
Кстати, вот мой код для вашей справки:
#include <iostream>
class ClassThatPrints
{
private:
const char **m_url;
public:
ClassThatPrints(const char ** url)
{
m_url = url;
std::cout << (*m_url) << std::endl;
}
void PrintAfterModify(void)
{
std::cout << (*m_url) << std::endl;
}
};
class ClassThatModifies
{
private:
const char *m_charPointer;
ClassThatPrints *m_ClassThatPrints;
public:
ClassThatModifies()
{
m_charPointer = "this is the original string";
std::cout << "Printing before modification:" << std::endl;
m_ClassThatPrints = new ClassThatPrints(&m_charPointer);
}
~ClassThatModifies() {
delete m_ClassThatPrints;
}
void ModifyStringAndPrint(void)
{
m_charPointer = "this is a modified string";
std::cout << "Printing after modification:" << std::endl;
m_ClassThatPrints->PrintAfterModify();
}
};
int main()
{
ClassThatModifies objClassThatModifies;
objClassThatModifies.ModifyStringAndPrint();
}
Если у вас есть что-то вроде этого:
void addHandler() {
const char* f_url = "blah blah";
m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));
}
void doStuff() {
addHandler();
m_eventCatcher.callProxy();
}
тогда проблема в том, что f_url выходит из области видимости, когда addHandler возвращается.
Если это так, то ваша версия bool также имела проблему, и (*m_dataValid) = false;
перезаписал некоторые другие данные.
const char* f_url = "blah blah";
это объявление означает, что у вас есть указатель на постоянную строку. Так что вы не можете сделать
strcpy(f_url, "hello world"); // copy to the preallocated place
но вы можете
f_url = "hello world"; // do pointer assignment
Если у вас следующая ситуация:
class ClassA {
const char* f_url = "blah blah";
public:
void method() {
f_url = "hello world";
}
};
class ClassB {
char** m_url;
public:
void print() {
cout << (* m_url); // m_url points to a string, allocated on the stack of ClassA::method()
}
};
имейте в виду, что строка "hello world"
размещается в стеке ClassA::method()
, И этот указатель больше не действителен, когда ClassA::method()
квиты. Для решения вопроса предлагаю следующее:
class ClassA {
static const int max_path = 256;
char f_url[max_path];
public:
void method() {
strcpy(f_url, "hello world");
}
};
class ClassB {
char** m_url;
public:
void print() {
cout << (* m_url);
}
};
const char* f_url = "blah blah"; // global
Может быть, вы неправильно понимаете эту строку?
Спецификатор const — это когда вы размещаете его, ссылаясь на ключевое слово слева от него.
Разрешается принимать это как первое ключевое слово, но потом, И ТОЛЬКО тогда, оно ссылается на свое право;)
Итак, ваша декларация гласит: (const char) * f_url
так что это указатель на const char.
И я предполагаю (я не знаю, как вы изменяете его значение в этом классе), вы получаете это сами, почему изменение значения const char может закончиться выводом мусора, не так ли?
Я предлагаю вам объявить это
char *const f_url = "blah blah";
это
char (* const) f_url
поэтому f_url — это постоянное значение адреса, указывающее на изменяемую область.
Но даже это не имеет особого смысла, потому что «бла-бла» — это адрес области памяти const, поэтому вы не можете изменить
(«бла-бла») [count] = что-нибудь;
тем не мение.
Так что вы должны просто сделать
char *const f_url = ThisIsACharArray[count];
и получить доступ к массиву символов, иначе String о f_url.
Или лучший способ для вас, как я предполагаю, просто не указывать const в объявлении и выделять изменяемую память для себя;)
Строка на самом деле не хранится в f_url
, Строка сохраняется где-нибудь еще, а также f_url
это указатель на это где-нибудь еще.
Если вы делаете это:
f_url = "new text"; // works fine
Когда ваша программа скомпилирована, она будет содержать строку "new text"
где-то в этом f_url
будет указывать на это — на некоторую память в середине самой программы.
f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB
fileUrl
является std :: string. fileUrl
имеет собственный указатель на строку, которую возвращает c_str. поскольку fileUrl
отвечает за управление этой строкой, когда fileUrl
выходит за рамки, память может быть повторно использована для чего-то другого — он не знает, что вы все еще используете эту память.
// I assume you meant f_url here, not m_url
strcpy(f_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(
Что это делает, зависит от того, что f_url
на самом деле указывает на. Если f_url
указывает на некоторую память в середине вашей программы (как с f_url = "blah blah";
) тогда это рухнет. Обычно это указывает на ошибку, поэтому операционная система не позволит вам это сделать.
Если бы это было разрешено, это могло бы произойти:
char *s = "hello world";
strcpy(s, "abracadabra");
printf("hello world"); // prints "abracadabra"
Что вам нужно сделать, это получить свой собственный блок памяти для хранения строки и освободить его, когда вы закончите:
f_url = new char[fileUrl.length() + 1];
strcpy(f_url, fileUrl.c_str());
// when you don't need the string any more
delete [] f_url;
или же:
f_url = strdup(fileUrl.c_str());
// when you don't need the string any more
free(f_url);
или просто сделать f_url
std::string
который обрабатывает управление памятью для вас. (Это самое простое решение!)