为什么复制构造函数不被“链接”?比如默认构造函数和析构函数?

发布于 2024-12-25 05:43:30 字数 1211 浏览 0 评论 0原文

为什么不链接复制构造函数(如默认构造函数或 dtor),以便在调用派生类的复制构造函数之前调用基类的复制构造函数?对于默认构造函数和析构函数,它们分别在从基到派生和从派生到基的链中调用。为什么复制构造函数不是这样?例如,以下代码:

class Base {
public:
    Base() : basedata(rand()) { }

    Base(const Base& src) : basedata(src.basedata) {
        cout << "Base::Base(const Base&)" << endl;
    }

    void printdata() {
        cout << basedata << endl;
    }

private:
    int basedata;
};

class Derived : public Base {
public:
    Derived() { }

    Derived(const Derived& d) {
        cout << "Derived::Derived(const Derived&)" << endl;
    }
};


srand(time(0));


Derived d1;      // basedata is initialised to rand() thanks to Base::Base()

d1.printdata();  // prints the random number

Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()
                 // Derived::Derived(const Derived&) is called but not
                 // Base::Base(const Base&)

d2.printdata();  // prints a different random number

复制构造函数不会(不能)真正复制对象,因为 Derived::Derived(const Derived&) 无法访问 basedata< /code> 来更改它。

我是否缺少关于复制构造函数的一些基本知识,因此我的思维模型不正确,或者这种设计是否有一些神秘(或不神秘)的原因?

Why aren't copy constructors chained (like default ctors or dtors) so that before the derived class's copy constructor is called, the base class's copy constructor is called? With default constructors and destructors, they are called in a chain from base-to-derived and derived-to-base, respectively. Why isn't this the case for copy constructors? For example, this code:

class Base {
public:
    Base() : basedata(rand()) { }

    Base(const Base& src) : basedata(src.basedata) {
        cout << "Base::Base(const Base&)" << endl;
    }

    void printdata() {
        cout << basedata << endl;
    }

private:
    int basedata;
};

class Derived : public Base {
public:
    Derived() { }

    Derived(const Derived& d) {
        cout << "Derived::Derived(const Derived&)" << endl;
    }
};


srand(time(0));


Derived d1;      // basedata is initialised to rand() thanks to Base::Base()

d1.printdata();  // prints the random number

Derived d2 = d1; // basedata is initialised to rand() again from Base::Base()
                 // Derived::Derived(const Derived&) is called but not
                 // Base::Base(const Base&)

d2.printdata();  // prints a different random number

The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access basedata to change it.

Is there something fundamental I'm missing about copy constructors so that my mental model is incorrect, or is there some arcane (or not arcane) reason for this design?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离不开的别离 2025-01-01 05:43:30

复制构造函数不会(不能)真正复制对象,因为 Derived::Derived(const Derived&) 无法访问 pdata来改变它。

当然可以:

Derived(const Derived& d)
    : Base(d)
{
    cout << "Derived::Derived(const B&)" << endl;
}

如果您没有在初始化列表中指定基类构造函数,则会调用其默认构造函数。如果您希望调用默认构造函数以外的构造函数,则必须指定要调用哪个构造函数(以及使用哪些参数)。

至于为什么是这样的:为什么复制构造函数应该与任何其他构造函数不同?作为一个实际问题的示例:

struct Base
{
    Base() { }
    Base(Base volatile&) { } // (1)
    Base(Base const&)    { } // (2)
};

struct Derived : Base
{
    Derived(Derived&) { }
};

您希望 Derived 复制构造函数调用哪个 Base 复制构造函数?

The copy constructor doesn't (can't) really make a copy of the object because Derived::Derived(const Derived&) can't access pdata to change it.

Sure it can:

Derived(const Derived& d)
    : Base(d)
{
    cout << "Derived::Derived(const B&)" << endl;
}

If you don't specify a base class constructor in the initializer list, its default constructor is called. If you want a constructor other than the default constructor to be called, you must specify which constructor (and with which arguments) you want to call.

As for why this is the case: why should a copy constructor be any different from any other constructor? As an example of a practical problem:

struct Base
{
    Base() { }
    Base(Base volatile&) { } // (1)
    Base(Base const&)    { } // (2)
};

struct Derived : Base
{
    Derived(Derived&) { }
};

Which of the Base copy constructors would you expect the Derived copy constructor to call?

时间海 2025-01-01 05:43:30

您可以:

Derived(const Derived& d) : Base(d) {
    cout << "Derived::Derived(const B&)" << endl;
}

这会调用 dBase 子对象上的 Base 复制构造函数。

“为什么”的答案我不知道。但通常没有答案。委员会只需选择其中一个选项即可。这似乎与语言的其余部分更加一致,例如 Derived(int x) 不会自动调用 Base(x)

You can:

Derived(const Derived& d) : Base(d) {
    cout << "Derived::Derived(const B&)" << endl;
}

This calls the Base copy constructor on the Base sub-object of d.

The answer for 'why' I don't know. But usually there's no answer. The committee just had to choose one option or the other. This seems more consistent with the rest of the language, where e.g. Derived(int x) won't automatically call Base(x).

再见回来 2025-01-01 05:43:30

这是因为默认情况下每个构造函数都会调用默认的基本构造函数:

Derived(const Derived& d) {
    cout << "Derived::Derived(const B&)" << endl;
}

将调用 Base()

这是由标准定义的。我更喜欢这样,而不是调用类上的复制构造函数。您当然可以明确地调用它。

That's because every constructor calls by default the default base constructor:

Derived(const Derived& d) {
    cout << "Derived::Derived(const B&)" << endl;
}

will call Base().

This is defined by the standard. I for one prefer it like this rather than calling the copy constructor on the class. You can of course call it explicitly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文