динамическое преобразование типов
[COLOR=black][SIZE=2]typedef[/SIZE][SIZE=2] map<string, [/SIZE][SIZE=2]void[/SIZE][SIZE=2]*>Sections;[/SIZE][/COLOR]
[SIZE=2][COLOR=#ffffff][COLOR=black]Sections *m_Sections;[/COLOR][/COLOR][/SIZE]
[COLOR=#ffffff][SIZE=2][COLOR=black]Values *m_Values;[/COLOR][/SIZE]
[SIZE=2][COLOR=#000000]m_Sections = new Sections;[/COLOR][/SIZE]
[COLOR=#000000]....[/COLOR]
[SIZE=2][COLOR=#000000]if (a<0)[/COLOR][/SIZE]
[SIZE=2][COLOR=#000000]m_Values = new Values;[/COLOR][/SIZE]
[SIZE=2][COLOR=#000000]else[/COLOR][/SIZE]
[SIZE=2][SIZE=2][COLOR=black]m_Values = [/COLOR][/SIZE][SIZE=2][COLOR=black]dynamic_cast[/COLOR][/SIZE][SIZE=2][COLOR=black]<Values*>((*m_Sections)[key]); // error [/COLOR][/SIZE][/SIZE]
[/COLOR]
error C2681: 'void *' : invalid expression type for dynamic_cast
Как правильно преобразовать динамически?
1. а где тут базовый и производный классы?
2. Почему нельзя просто указать что-то типа
((*m_Values)[key]) = *((*m_Sections)[key]);
Как правильно преобразовать динамически?
В данном случае - динамически никак, да и не за чем.
Отказывайся от void* в своих программах. Это дурной тон и плохой стиль для C++.
dynamic_cast тоже нужно избегать. Это тоже плохой стиль.
Всё можно сделать намного красивее и правильнее без этих уродств.
Отказывайся от void* в своих программах. Это дурной тон и плохой стиль для C++.
dynamic_cast тоже нужно избегать. Это тоже плохой стиль.
Всё можно сделать намного красивее и правильнее без этих уродств.
Мне в (*m_Sections)[key] необходимо хранить как Values* так и char*
а затем при чтении массива преобразовывать к соотв. типу.
{
cout<<"param name: <"<<iIter_Sections->first.c_str()<<">"<<'\n';
Values *m_Values = dynamic_cast<Values*>(iIter_Sections->second);
if (!m_Values)
cout<<"param value: "<<(char*)iIter_Sections->second<<'\n';
else
{
Values *m_Values = (Values*)iIter_Sections->second;
for(iIter_Values = m_Values->begin(); iIter_Values != m_Values->end(); iIter_Values++)
{
cout<<"sybparam name: <"<<iIter_Values->first.c_str()<<">"<<'\n';
cout<<"sybparam value: "<<iIter_Values->second.c_str()<<""<<'\n';
}
}
}
Насколько я могу судить - почему не сделать класс-контейнер, который хранит Values* и char*, и что-бы его поведение управлялось его внутренней логикой?
пробовал... только если (*m_Sections)[kye] = (char*) = пустая строка
тогда static_cast или reinterpret_cast выдают что это тип Values* соответсвенно m_Values->begin() == AV
А ещё лучше сделать один базовый класс-контейнер и два наследника: один для Values* и второй для char*.
Не уверен, что это лучше.
Если реализовать через единый класс-контейнер, то не нужно будет вообще конвертировать типы. А я думаю, что это предпочтительней реализации с наследованиями.
Если реализовать через единый класс-контейнер, то не нужно будет вообще конвертировать типы. А я думаю, что это предпочтительней реализации с наследованиями.
Единый контейнер для разнотипных объектов - это получается вариация на тему злобного Variant-типа.
Не обязательно. Я имею ввиду что-то вроди:
{
...
private:
Values* m_val;
char * m_str;
public:
char* c_str()
{
return m_str;
};
Values* c_val()
{
return m_val;
};
...
}
То-есть, примерно так, как это в стль делается :)
{
public:
enum Type{StringType, ArrayType};
SomeClass(string str)
{
s = str;
type = StringType;
}
SomeClass(Values *v)
{
val = v;
type = ArrayType;
}
Type GetType (void){return type;}
Values * GetArray(void){return val;}
Values * GetString(void){return s;}
private:
string s;
Values *val;
Type type;
}
соответственно вызов:
if (pSomeClass->GetType() == pSomeClass->StringType)
string str = pSomeClass->GetString();
else....
мож и не красиво, но работает
Values * GetString(void){return s;}
Values * GetString(void){return s;}
в браузере писал... в реальности он несколько больше (сам класс) и естественно без ошибок, т.к. работает как надо
{
virtual string GetStr() = 0;
};
struct MyString : public BaseClass
{
string str;
string GetStr(){return str;}
MyString(string s):str(s){}
};
struct MyInt : public BaseClass
{
int iVar;
string GetStr(){throw iVar; return "";}
MyInt(int i):iVar(i){}
};
int main()
{
vector<BaseClass*> sections;
MyString sFirst("first"), sSecond("second");
MyInt iFirst(1), iSecond(2);
sections.push_back(&sFirst);
sections.push_back(&iFirst);
sections.push_back(&sSecond);
sections.push_back(&iSecond);
for(int i = 0; i < sections.size(); i++)
{
try{ cout << sections->GetStr() << endl;}
catch(int gg){ cout << "it's not string, but int: " << gg << endl; }
}
}
Не буду говорить что этот метод лучше, но он позволяет не хранить по 2 переменные в каждом экземляре классов. Ну и морочиться с enum не надо.