通过派生类创建 C++ 基类成员 [已关闭]

C++ Base class member creation via derived class [closed]

提问人:Panos Kontogiannis 提问时间:2/19/2023 更新时间:2/20/2023 访问量:63

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

9个月前关闭。

我在理解以下代码时遇到困难:

class Base{
   Base(){/* do stuff */};
};

class Deriv: public Base{
   Deriv(){/* do stuff */};
};

// I have a problem understanding the purpose of the next line
Base &foo = *(new Deriv());
C++ 派生 基类

评论

3赞 Quimby 2/19/2023
嗯,这是一个等待发生的内存泄漏。但是你到底不清楚什么?它只是取消引用指针并将其分配给引用。
1赞 Some programmer dude 2/19/2023
它本质上等同于类似的东西,然后立即失去。Base* foo_temp = new Deriv(); Base& foo = *foo_temp;foo_temp
0赞 user17732522 2/19/2023
@PanosKontogiannis 这条线没有错。有引用和有指针一样好。
1赞 sklott 2/19/2023
无法检查内存是否已分配在 C++ 中,无需检查是否分配了内存。默认情况下,如果未分配内存,则会引发异常。如果要检查内存是否手动分配,则需要添加到新表达式中。std::bad_alloc(std::nothrow)
0赞 Panos Kontogiannis 2/19/2023
谢谢,现在很清楚了。作者只是想使用而不是在程序的其余部分,如果他只是使用foo.memberfoo->memberBase* foo=new Deriv();

答:

1赞 sens 2/19/2023 #1

首先,您需要熟悉多态性、引用、取消引用和临时对象行为。

  1. 某个类的每个对象都可以表示为(可以被视为)层次结构中较高的类的对象。

最流行的例子是动物。许多消息来源都用它来描述这个话题。

class Animal {};

class Dog : public Animal {};

int main() {
    // All dogs are animals: OK
    Animal* a = new Dog();

    // Not every animal is a dog: Error
    Dog* d = new Animal()
}

想象一下,您正在创建一个游戏,其中您的玩家有一只宠物。

class WongPlayer {
    Dog* pet;
}

如果你这样说,你将能够只养狗作为宠物。

class CorrectPlayer {
    Animal* pet;
}

在这种情况下,您可以将继承自 Animal 的任何类作为 pet。

这只是使用多态性的一个简单例子。

  1. 引用。 解释什么是引用的最好方法是将它们视为别名。 创建引用与创建别名完全相同。 而所有的限制也都通过这种方式得到了很好的理解。

例:

int a = 5;
int& b = a; // b is alias of a
b = 3; // a = 3
  1. 取消引用。 new 返回一个指针,因此要使用它指向的对象,必须首先取消引用它。

例:

int* val = new int(1);
val = 5; // Error can't assign int to pointer
*val = 5; OK
 delete val;
  1. 临时对象,它们会立即创建和删除。

例:

class A {
    public:
        A() { std::cout << "Created" << std::endl;}
        ~A() { std::cout << "Destroyed" << std::endl;}
}

int main {
    A();
    std::cout << "Should it be printed before destruction? No!" << std::endl;
    return 0;
}

在本例中,请执行以下操作: 在堆中分配对象并返回其指针。

new Deriv()

取消引用该指针

*(new Deriv())

创建一个引用并将其与新创建的对象绑定。

在这里,我们开始遇到一些问题。它不是一个临时的对象!堆中的对象永远不会被破坏。 这是明显的内存泄漏

我不知道你为什么要创建一个参考。 最好的方法是创建指针。

Base* ptr = new Deriv();

然后

delete ptr;

就是这样。

但是,是的,您也可以像这样删除它

Base& ref = *(new Deriv());
delete &ref;