Maison  >  Questions et réponses  >  le corps du texte

c++中与继承和static相关的一些问题

#include <iostream>

using namespace std;
class A
{
public:
    static int a;
    int b = 1;
    void test()
    {
        cout << "called A\n";
    }
};
int A::a = 10;

class B : public A
{
public:
    void test()
    {
        cout << "called B\n";
    }
};
int main()
{
    cout << B::a << endl;
    B* ptr_B = new B();
    ptr_B -> test();
    A* ptr_A = (A*)ptr_B;
    ptr_A -> test();
    cout << ptr_A << ' ' << ptr_B << endl;
    return 0;
}

代码如上,自己有几个地方比较困惑。
1.为什么static变量不能就地初始化,c++11不是就已经允许其它变量可以就地初始化吗?
2.当实例化派生类的时候,调用了基类的构造函数,那是相当于有一个匿名的基类对象被构造了吗?还是不存在这样的一个匿名对象,只是基类构造的部分是作为派生类的一部分而存在的?
3.用派生类的指针和基类的指针,当它们都是指向派生类对象的地址的时候,调用同名函数,它们的底层机制是如何实现的?为什么即便指向的是相同的地址,但是它们调用的时候却可以调用不同的函数?编译器层面是如何解释的哦?

大家讲道理大家讲道理2713 Il y a quelques jours493

répondre à tous(2)je répondrai

  • PHPz

    PHPz2017-04-17 14:00:28

    1, C++11以后static成员可以直接初始化,但是仅限于字面量类型(literal type).
    2, 准确的说,是属于基类的成员被初始化,并非匿名,而且这些成员也是派生类的一部分。
    3, 这个问题比较大,你可以去了解一下C++的对象内存模型和virtual function的调用机制是怎样的,我可以简单的和你介绍一下:
    (1) 带有虚函数里类里有一个隐秘的指针成员(vptr),它指向程序里的一块只读区域里的一张虚表(vtable)。
    (2) 带有虚函数的类经过编译后都会有一张对应的虚表。
    (3) 这个表里存了实际上这个类里虚函数的实现的函数地址。
    (4) 当你调用一个对象的虚函数时,程序就会从它的vptr指向的vtable来找到实际上应当调用的函数。

    répondre
    0
  • 黄舟

    黄舟2017-04-17 14:00:28

    1.只有成员变量和 static 的 const 的变量还有 enum 可以就地初始化,之所以 non-static 的不能够就地初始化,按照 Bjarne Stroustrup 的话来说就是:

    A class is typically declared in a header file and a header file is
    typically included into many translation units. However, to avoid
    complicated linker rules, C++ requires that every object has a unique
    definition.
    That rule would be broken if C++ allowed in-class
    definition of entities that needed to be stored in memory as objects.

    2.作为派生类实例的一部分。
    3.这个要分虚函数和非虚函数来考虑,你这里的test()是非虚函数,所以不会查找 v-table,按照变量的类型定义来查找对应实现;如果是virtual方法则会按照对象实际的类的对应方法。编译器层面对于你这里的例子而言,单纯的就是相当于std::bind(&B::test, ptr_B)();std::bind(&A::test, ptr_A)();,所以函数实现当然是不同的了。

    répondre
    0
  • Annulerrépondre