Derived1
* hh = static_cast&(new Base);

hh-&>derivedfunction(); // 这里竟然是可以的 为什么呢 hh指向的是一个基类对象啊??而且即使derivedfunction里面用到派生类的私有成员也是可以的,

这到底是为什么啊???

// 运行的结果就是列印出了33

// 我疑惑的是 实际上 指针指向的内存应该只保存了base对象的大小

// 可是这里可以设置继承类的成员变数 还可以列印出来 也没有报如何错误

// 我用的是gcc的编译器 具体版本

//=== TDM-GCC Compiler Suite for Windows ===

//--- GCC 4.7 4.8 Series ---//*** Standard MinGW 32-bit Edition ***

#include&

class Base
{
public:
virtual void print_b() {};
};
class Derived1:public Base
{
public:
virtual void print_b()
{
std::cout&(new Base);
hh-&>setcc(33);
hh-&>jessica();
}


undefined behaviour,因为一个基类对象被强制访问不存在的子类sub-object的成员的内存位置。

你的问题是初学者很典型的问题,涉及如下概念:

编译时类型,运行时类型,非虚成员函数的本质,类对象的内存布局。

建议你好好阅读《深入探索C++对象模型》

针对 @vczh 答案补充点材料:static_cast conversion

static_cast不会编译错误,只是undefined behaviour2) If new_type is a pointer or reference to some class D and the type of expression is a pointer or reference to its non-virtual base B, static_cast performs a downcast. Such static_cast makes no runtime checks to ensure that the objects runtime type is actually D, and may only be used safely if this precondition is guaranteed by other means, such as when implementing static polymorphism. Safe downcast may be done withdynamic_cast.
为什么我觉得static_cast那一步就会有编译错误


你以为编译器会去判断指针实际指著什么对象?拿衣服,指针是什么类型,编译器就当他是什么类型
首先这个是能够编译通过的,只不过行为是undefined,毕竟是static_cast。cast之后编译器就认为hh是一个Derived1类型的指针了,当然可以使用任何成员。你说的没错,Base确实是只保存了一个虚指针,sizeof(Base)是4(32位编译器下)不过题主你的main函数假如改成这样,运行就会直接崩溃了(have a try~):

int main()
{
Base a[2];
Derived1 * hh = static_cast&(a + 0);
hh-&>setcc(33);
hh-&>jessica();//works
a[1].print_b();//Oops, crashes in g++, in MSVC it is OK
Derived1 * hh1 = static_cast&(a + 1);
hh1-&>print_b();//Oops, finally in MSVC it crashes
return 0;
}

有趣的是MSVC运行a[1].print_b()的时候不会崩溃,这个其实也很好理解,由于编译器的优化,寄存器在main函数开始的时候已经把虚表里存的指针放在寄存器中准备call过去了(毕竟邻近的都要用嘛,这样可以省下一次读内存的cost),好吧这个扯远了,题主可以无视。。。

不过呢,如果你能明白为什么这里会崩溃,那我觉得你的这个问题也就解决了。
先不论static_cast会不会报错(因为按照你的思路,应该用的reinterpret_cast)。因为Derived1::cc并不是虚函数,你的Derived1 hh只是按照函数设定的意义去操作,尽管操作的int cc在你new Base的内存之外(对, 你访问了未分配的内存)。当然hh-&>jessica也可以工作。

成员函数的本质是存在于程序text段的一段代码,运行时拷贝进内存,与类无关(类的大小由类成员及虚函数指针确定) 调用成员函数时默认前面有一个类对象的指针this,这也是为什么可以在成员函数里面使用this和成员变数的原因,而这里就是由于这个特性导致的奇异现象。


因为你没有使用成员函数,C++成员函数的语法糖而已。
你先说说什么是多态?
因为你用的是c++这门奇葩的语言
推荐阅读:
相关文章