C++:多态复制构造函数可以工作吗?

发布于 2024-07-25 20:56:30 字数 514 浏览 5 评论 0原文

考虑一下:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = new A( *b1 ); // ERROR...but what if it could work?
    return 0;
}

如果“new A( b1 )”能够解析创建新的 B 副本并返回 A,C++ 会被破坏吗?

这还有用吗?

Consider:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = new A( *b1 ); // ERROR...but what if it could work?
    return 0;
}

Would C++ be broken if "new A( b1 )" was able to resolve to creating a new B copy and returning an A?

Would this even be useful?

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

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

发布评论

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

评论(6

萌辣 2024-08-01 20:56:30

您是否需要此功能,或者这只是一个思想实验?

如果您需要这样做,常见的习惯用法是使用 Clone 方法:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    virtual A *Clone () = 0;
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    A *Clone() { return new B(*this); }
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = b1->Clone();
    return 0;
}

Do you need this functionality, or is this just a thought experiment?

If you need to do this, the common idiom is to have a Clone method:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    virtual A *Clone () = 0;
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    A *Clone() { return new B(*this); }
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = b1->Clone();
    return 0;
}
沉鱼一梦 2024-08-01 20:56:30

您真正要寻找的是虚拟复制构造函数, eduffy 发布的是标准方法。

还有使用模板来完成此操作的巧妙方法。 (免责声明:自我推销)

What you're really looking for is called a virtual copy constructor, and what eduffy posted is the standard way of doing it.

There are also clever ways of doing it with templates. (disclaimer: self-promotion)

虫児飞 2024-08-01 20:56:30

只是对 eduffy 的答案做了一点补充:
代替

class B : public A {
  ...
  A *Clone() { return new B(*this); } 
  ...

};

你可以这样声明:

class B : public A {
  ...
  B *Clone() { return new B(*this); } // note: returning B *
  ...

};

它仍然被认为是虚拟 A::Clone(); 的有效重写,并且如果直接通过 B * 调用会更好

Just a small addition to the answer by eduffy:
Instead of

class B : public A {
  ...
  A *Clone() { return new B(*this); } 
  ...

};

you can declare it like this:

class B : public A {
  ...
  B *Clone() { return new B(*this); } // note: returning B *
  ...

};

It's still considered a valid overriding of the virtual A::Clone(); and is better if called directly through B *

ι不睡觉的鱼゛ 2024-08-01 20:56:30

假设您有适当的重载,则该表达式

new A(*b1)

已经具有含义。

如果它被赋予了不同的含义,您就必须提供另一种方式来获得其他含义。 鉴于已经有一种方法可以获得您想要的含义,这有点毫无意义:

new B(*b1)

并猜测哪个读起来更清晰。

The expression

new A(*b1)

already has a meaning, supposing you had the appropriate overload.

If it was given a different meaning, you'd have to provide another way to get the other meaning. This is kind of pointless given that there is already a way to get the meaning you want:

new B(*b1)

And guess which is clearer to read.

oО清风挽发oО 2024-08-01 20:56:30

是的。 没有。

有多种方法可以实现克隆(例如,或多或少标准的clone()方法、对象工厂的参数化变体、有或没有可配置的依赖注入),而无需改变现有程序的含义,或使其无法创建当派生类在编译单元内已知时,基类的实例。

构造函数和析构函数足够复杂,初学者很难理解。 向它们注入更多的复杂性是不明智的。

Yes. No.

There are a number of ways of implementing cloning (e.g. the more or less standard clone() method, parameterized variations of object factories, with or without configurable dependency injection) without changing the meaning of existing programs, or making it impossible to create instances of base classes when a derived class is known within a compilation unit.

Constructors and destructors are sufficiently complex to understand for beginners as is. Injecting even more complexity into them would be unwise.

嘴硬脾气大 2024-08-01 20:56:30

如上所述,有多种方法可以实现这一点。

要回答您的问题,如果 new A( *b1 ) 返回 B 的新实例,那么这将不起作用。

int main()
{
    A* b1 = new B( 1, 2 );
    A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
    return 0;
}

As pointed out above there are a number of ways of implementing this.

To answer your question if new A( *b1 ) returned an new instance of B then this would not work.

int main()
{
    A* b1 = new B( 1, 2 );
    A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文