通过派生类创建C++基类成员

huangapple go评论66阅读模式
英文:

C++ Base class member creation via derived class

问题

I'm having difficulties understanding the following code:

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());
英文:

I'm having difficulties understanding the following code:

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());

答案1

得分: 1

First, you need to be familiar with Polymorphism, references, dereferencing, and temporary object behavior.

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

这方面最常见的例子是动物。许多来源用它来描述这个主题。

class Animal {};

class Dog : public Animal {};

int main() {
    // 所有狗都是动物:OK
    Animal* a = new Dog();

    // 并非每个动物都是狗:错误
    Dog* d = new Animal();
}

想象一下,你正在创建一个游戏,玩家有宠物。

class WrongPlayer {
    Dog* pet;
}

按照这种方式,你只能拥有狗作为宠物。

class CorrectPlayer {
    Animal* pet;
}

在这种情况下,你可以拥有任何从Animal继承的类作为宠物。这只是多态性用法的一个简单示例。

  1. 引用。
    解释引用是什么的最佳方式是将它们视为别名。
    创建引用与创建别名完全相同。
    通过这种方式也很容易理解所有的限制。

示例:

int a = 5;
int& b = a; // b是a的别名
b = 3; // a = 3
  1. 解引用。
    new 返回一个指针,所以要处理它所指向的对象,你必须首先对其进行解引用。

示例:

int* val = new int(1);
val = 5; // 错误,不能将整数分配给指针
*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 << "应该在销毁之前打印吗?不应该!" << std::endl;
    return 0;
}

在你的情况下,你执行以下操作:
在堆中分配一个对象并返回其指针。

new Deriv()

对该指针进行解引用。

*(new Deriv())

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

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

我不知道为什么你要创建一个引用。
最佳方法是创建一个指针。

Base* ptr = new Deriv();

然后

delete ptr;

就这样。

但是,你也可以这样删除它

Base& ref = *(new Deriv());
delete &ref;
英文:

First, you need to be familiar with Polymorphism, references, dereferencing and temporary object behavior.

  1. Every object of some Class can be represented as (can be treated as) an object of a Class that is higher in the hierarchy.

The most popular examples of this are animals. Many sources describe this topic with it.

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()
}

Imagine you are creating a game, where your player has a pet.

class WongPlayer {
    Dog* pet;
}

If you put it this way, you will be able to have only Dog as pet.

class CorrectPlayer {
    Animal* pet;
}

In this case, you can have as pet any class that inherits from Animal.

This was just one simple example of the usage of Polymorphism.

  1. References.
    The best way of explaining what references are is to treat them as aliases.
    Creating a reference is completely identical of creating an alias.
    And all the restrictions are also well understood by this way.

Example:

int a = 5;
int&amp; b = a; // b is alias of a
b = 3; // a = 3
  1. Dereferencing.
    new returns a pointer, so to work with the object it points to, you have to first dereference it.

Example:

int* val = new int(1);
val = 5; // Error can&#39;t assign int to pointer
*val = 5; OK
 delete val;
  1. Temporary objects, they are created and deleted immediately.

Example:

class A {
    public:
        A() { std::cout &lt;&lt; &quot;Created&quot; &lt;&lt; std::endl;}
        ~A() { std::cout &lt;&lt; &quot;Destroyed&quot; &lt;&lt; std::endl;}
}

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

In your case, you do the following:
Allocate an object in heap and return its pointer.

new Deriv()

Dereference that pointer

*(new Deriv())

Create a reference and bind it with newly created object.

And here we start to have some problems. It is not a temporary object! Your object in heap never gets destroyed.
It is a clear memory leak

I don't know why are you creating a reference.
The best way is to create a pointer.

Base* ptr = new Deriv();

And then

delete ptr;

And that's it.

But yes, you can also delete it like this

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

huangapple
  • 本文由 发表于 2023年2月19日 18:59:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499635.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定