从基础到派生的 C++ 转换
c++ casting from base to derived
我从基类访问派生类的值时遇到了一些麻烦。我的代码是:
#include <iostream> // std::cout, std::endl
#include <iomanip> // std::setfill, std::setw
#include <vector>
enum EType
{
E_TYPE_NONE=0,
E_TYPE_BASE,
E_TYPE_DERIVED_1,
E_TYPE_DERIVED_2
};
struct Base
{
Base() : mEType(E_TYPE_BASE), a(0), b(0), c(0) {}
virtual ~Base() {}
virtual Base* Get() {return this;}
EType mEType;
unsigned short a;
unsigned short b;
unsigned short c;
};
struct Derived1 : public Base
{
Derived1() : Base()
{
mEType = E_TYPE_DERIVED_1;
a = 1;
b = 2;
c = 3;
d = 4;
}
virtual ~Derived1() {}
virtual Derived1* Get() {return this;}
unsigned short d;
};
struct Derived2 : public Base
{
Derived2() : Base()
{
mEType = E_TYPE_DERIVED_2;
a = 5;
b = 6;
c = 7;
e = 8;
}
virtual ~Derived2() {}
virtual Derived2* Get() {return this;}
unsigned short e;
};
struct Foo
{
std::vector<Base> mObj;
};
int main(int argc, char* argv[])
{
Foo myCollection;
Derived1 obj1;
Derived2 obj2;
Base obj3;
myCollection.mObj.push_back(obj1);
myCollection.mObj.push_back(obj2);
myCollection.mObj.push_back(obj3);
//=========================================================================
std::cout << "base1 = " << myCollection.mObj[0].a << "; " <<
myCollection.mObj[0].b << "; " <<
myCollection.mObj[0].c << std::endl;
Derived1* current1;
// this way i got access violation when i try to print current1
//current1 = dynamic_cast<Derived1*>(myCollection.mObj[0].Get());
current1 = dynamic_cast<Derived1*>((Derived1*)myCollection.mObj[0].Get());
std::cout << "derived1 = " << current1->a << "; " <<
current1->b << "; " <<
current1->c << "; " <<
current1->d << std::endl;
//=========================================================================
std::cout << "base2 = " << myCollection.mObj[1].a << "; " <<
myCollection.mObj[1].b << "; " <<
myCollection.mObj[1].c << std::endl;
Derived2* current2;
current2 = (Derived2*)myCollection.mObj[1].Get();
std::cout << "derived2 = " << current2->a << "; " <<
current2->b << "; " <<
current2->c << "; " <<
current2->e << std::endl;
//=========================================================================
std::cout << "base3 = " << myCollection.mObj[2].a << "; " <<
myCollection.mObj[2].b << "; " <<
myCollection.mObj[2].c << std::endl;
//=========================================================================
std::cout << "ENTER to exit...";
std::cin.ignore(10000, 'n');
return 0;
}
结果是:
base1 = 1; 2; 3
derived1 = 1; 2; 3; 47472
base2 = 5; 6; 7
derived2 = 5; 6; 7; 47472
base3 = 0; 0; 0
ENTER to exit...
预期结果为:
base1 = 1; 2; 3
derived1 = 1; 2; 3; 4
base2 = 5; 6; 7
derived2 = 5; 6; 7; 8
base3 = 0; 0; 0
ENTER to exit...
谁能帮助我理解:
- 有没有更好的方法从基础转换为派生,而不是使用 Get() 方法?
- 为什么我没有得到预期的结果?
谢谢
你正在做的不是继承。您正在隐藏成员函数。您正在对象上静态调用函数。
在C++中,如果将基类中的成员声明为 Brian 正确地指出,您可以对覆盖的虚函数使用协变返回。然而,其余的仍然是正确的。virtual
,并且稍后想要重写它,则必须保留其整个签名,包括返回类型。您正在更改返回类型并将其重新声明为 virtual
,这很混乱,但特别是它仅适用于静态调用。
这没关系,因为您甚至不使用指针来存储对象,而是将它们静态存储为指针中的Base
。您正在分配较大的对象(同样是静态的,您对它有整个迷恋),然后将它们混合在一起形成向量中较小的Base
对象,删除其余数据并损坏组合vtable
,您是对所有对象的静态调用Base::Get()
(而不是"派生"Get
),获取指向Base *
对象的指针(有点有效),然后向编译器撒谎说它是别的东西, 然后你正在使用你撒谎的记忆。
老实说,我很惊讶它不仅崩溃,您可能是在启用内存保护的情况下以调试模式构建的(如果是 MSVC,则会收到您忽略的运行时警告)。
首先,不要使用结构和公共字段,在需要时使用带有公共方法的类(getter 读取值而无法编辑它们)。
使用虚拟方法,以便您可以通过在指向基类的指针/引用上调用派生类中的方法来调用它们,返回 2 行并再次读取。
只要虚拟方法具有相同的签名,它们就可以按预期工作,否则您只需使用 2 种不同的方法
virtual Derived1* Get() {return this;} //in derived class1
不同于
virtual Base* Get() {return this;}
但你可以做到
virtual Base* Get() {return static_cast<Base*>(this);} //in derived class1
现在您有 2 种具有相同签名的方法。那会起作用
Derived1 derived;
Base base;
Base * derivedbase = derived.Get();
if(derivedbase->Get() == derivedbase)
cout<<"Nice eh?"<<endl;
using namespace std;
cout<<derived.d<<endl;
cout<<derived.a<<endl;
cout<<base.a<<endl;
cout<<derivedbase->a<<endl;
//cast to derived
Derived1 *againderived = dynamic_cast<Derived1*>(derivedbase);
cout<<againderived->d<<endl;
//ops that would fail
//Derived2 *wrongcast = dynamic_cast<Derived2*>(derivedbase);
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++