首頁  >  問答  >  主體

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 天前494

全部回覆(2)我來回復

  • 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來找出實際上應當呼叫的函數。

    回覆
    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 slink rules, Cunits. 🎜>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.這個要分虛函數和非虛函數來考慮,你這裡的
    是非虛函數,所以不會查找v-table,按照變量的類型定義來查找對應實現;如果是test()方法則會依照物件實際的類別的對應方法。編譯器層面對於你這裡的例子而言,單純的就是相當於virtualstd::bind(&B::test, ptr_B)();,所以函數實作當然是不同的了。 std::bind(&A::test, ptr_A)();

    回覆
    0
  • 取消回覆