C++ 引用基类的成员变量会导致访问冲突

C++ 引用基类的成员变量会导致访问冲突,c++,reference,derived-class,C++,Reference,Derived Class,我已经将派生类的成员变量定义为基类的成员变量的引用。我这样做是因为在派生类中,引用的名称比基类中原始变量的名称更有意义 现在我正在创建一个char缓冲区,其大小足以包含派生类的对象。我定义了一个指向派生类的指针,并使用static\u cast,将其指向缓冲区 如果派生类的成员函数使用基类中定义的原始名称取消基类成员变量的引用,则没有问题 但如果使用引用的名称取消引用,则会出现内存访问冲突 为什么会有不同的行为 如何实现我要做的事情,即在派生类中用不同的名称引用变量 class B { publ

我已经将派生类的成员变量定义为基类的成员变量的引用。我这样做是因为在派生类中,引用的名称比基类中原始变量的名称更有意义

现在我正在创建一个char缓冲区,其大小足以包含派生类的对象。我定义了一个指向派生类的指针,并使用
static\u cast
,将其指向缓冲区

如果派生类的成员函数使用基类中定义的原始名称取消基类成员变量的引用,则没有问题

但如果使用引用的名称取消引用,则会出现内存访问冲突

  • 为什么会有不同的行为
  • 如何实现我要做的事情,即在派生类中用不同的名称引用变量

    class B {
    public:
        int x;
        B () : x(10) {}
    };
    
    class D : public B {
    public:
        int &y{ x };
        // No problem here:
        inline bool IsXTen () { return ((x == 10) ? true : false); }
        // Memory Access Violation occurs here:
        inline bool IsYTen () { return ((y == 10) ? true : false); }
    };
    
    int main(int argc, char* argv[])
    {
        char buf[sizeof (class D)] = { 0 };
        void *pVoid = buf;
        class D *pd = static_cast<class D*>(pVoid);
    
        if (pd->IsXTen ()) {
            return 1;
        }
    
        if (pd->IsYTen ()) {
            return 2;
        }
    
        return 0;
    }
    
    B类{
    公众:
    int x;
    B():x(10){}
    };
    D类:公共B类{
    公众:
    int&y{x};
    //这里没问题:
    内联boolisxten(){return((x==10)?true:false);}
    //内存访问冲突发生在以下位置:
    内联bool-IsYTen(){return((y==10)?true:false);}
    };
    int main(int argc,char*argv[])
    {
    char buf[sizeof(D类)]={0};
    void*pVoid=buf;
    D类*pd=静态施法(pVoid);
    如果(pd->IsXTen()){
    返回1;
    }
    if(pd->IsYTen()){
    返回2;
    }
    返回0;
    }
    

  • 引用很可能作为指针存储在对象的内存布局中(请参阅)。您没有调用初始化该引用/指针的构造函数,因此使用它是未定义的。

    该引用可能作为指针存储在对象的内存布局中(请参阅)。您没有调用初始化该引用/指针的构造函数,因此使用它是未定义的。

    如注释中所述,您这样做的方式不会构造对象。在这种情况下,请使用“placement new”(新放置)来正确构建它:

    char buf[sizeof (class D)] = { 0 };
    
    // Class not initialized, constructors not called
    // class D *pd = static_cast<class D*>(pVoid);
    
    // Object is properly initialized
    class D *pd = new (buf) D;
    
    charbuf[sizeof(D类)]={0};
    //类未初始化,未调用构造函数
    //D类*pd=静态施法(pVoid);
    //对象已正确初始化
    D类*pd=新(buf)D类;
    
    如注释中所述,您的操作方式并不构成对象。在这种情况下,请使用“placement new”(新放置)来正确构建它:

    char buf[sizeof (class D)] = { 0 };
    
    // Class not initialized, constructors not called
    // class D *pd = static_cast<class D*>(pVoid);
    
    // Object is properly initialized
    class D *pd = new (buf) D;
    
    charbuf[sizeof(D类)]={0};
    //类未初始化,未调用构造函数
    //D类*pd=静态施法(pVoid);
    //对象已正确初始化
    D类*pd=新(buf)D类;
    

    为什么要投这个?您有一个足够大的缓冲区,可以容纳
    D
    ,但缓冲区中没有
    D
    静态\u cast
    不会构造
    D
    。因此,成员
    x
    y
    不保证按照各自类别定义中的规定进行初始化。因此,访问它们中的任何一个都会导致未定义的行为。这是一种非常奇怪的方式。为什么不干脆
    newd()而不是所有的环?另外,
    D类*pd
    ——该
    类是冗余的。您甚至可能应该使用
    new
    。@clear“如果您不想调用构造函数(您可以),请使用
    newd;
    newd
    调用构造函数。@tkausl我被告知它没有。我从来没用过。不打电话给构造器就像你的车没有刹车。你为什么要投这个?您有一个足够大的缓冲区,可以容纳
    D
    ,但缓冲区中没有
    D
    静态\u cast
    不会构造
    D
    。因此,成员
    x
    y
    不保证按照各自类别定义中的规定进行初始化。因此,访问它们中的任何一个都会导致未定义的行为。这是一种非常奇怪的方式。为什么不干脆
    newd()而不是所有的环?另外,
    D类*pd
    ——该
    类是冗余的。您甚至可能应该使用
    new
    。@clear“如果您不想调用构造函数(您可以),请使用
    newd;
    newd
    调用构造函数。@tkausl我被告知它没有。我从来没用过。不打电话给建设者就像你的车里没有休息。谢谢你的回答。事实证明,
    placement new
    无法解决我的问题,因为构建对象会导致包含数据的缓冲区被覆盖。我试图基于缓冲区中已经存在的数据创建一个对象,而不复制该数据。谢谢您的回答。事实证明,
    placement new
    无法解决我的问题,因为构建对象会导致包含数据的缓冲区被覆盖。我试图基于缓冲区中已经存在的数据创建一个对象,而不复制该数据。谢谢您的回答。我现在明白了为什么它不起作用,但这并不能解决我的问题。因为问题是引用没有初始化,所以您唯一的选择是初始化引用或不使用引用。如果您想初始化引用,请创建一个这样做的函数或研究如何做。如果您不需要引用,创建一个getter。感谢您的回答。我现在明白了为什么它不起作用了,但这并不能解决我的问题。因为问题是引用没有初始化,所以您唯一的选择是初始化引用或不使用引用。如果您想初始化引用,请创建一个函数,或者研究如何做。如果您不需要引用,请创建一个getter。