Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将派生对象传递给C++;? 我认为我对C++继承有误解。_C++_Inheritance_Polymorphism - Fatal编程技术网

如何将派生对象传递给C++;? 我认为我对C++继承有误解。

如何将派生对象传递给C++;? 我认为我对C++继承有误解。,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,比如说,我继承了这一经典遗产: class A{ public: virtual void method1() =0; virtual ~A() = default; } class B : public A{ public : void method1(){doSomething();} } class C : public A{ public : void m

比如说,我继承了这一经典遗产:

    class A{
    public: 
        virtual void method1() =0;
        virtual ~A() = default;
    }

    class B : public A{
    public :
        void method1(){doSomething();}
    }

    class C : public A{
    public :
        void method1(){doSomethingElse();}
    }
我如何使另一个类Q拥有类型为B或C的对象,而不事先知道它是哪种类型?(我的意思是我们知道它是A型的,仅此而已)


谢谢你的阅读

类必须确切地知道其所有子对象的类型。动态多态性只能通过间接方式实现。因此,虽然不可能包含多态类型的对象,但可以拥有一个。例如:

struct Q {
    shared_ptr<A> object; // could point to B or C
}
structq{
共享的\u ptr对象;//可以指向B或C
}

由于您不想
Q
了解
B
C
,因此必须通过指针间接存储
A
,因为您无法知道
B
C
或未知的派生类
D
需要多少存储空间。对于由Q动态分配和拥有的单个对象,经典的解决方案是a

由于默认情况下,
std::unique_ptr
使用
delete
删除对象,因此还需要一个虚拟析构函数

#include"A.hpp"
#include<memory>

class Q {
    std::unique_ptr<A> a;
public:
    Q(std::unique_ptr<A> ai) : a{std::move(ai)} {}
};
#包括“A.hpp”
#包括
Q类{
std::唯一的ptr a;
公众:
Q(std::unique_ptr ai):a{std::move(ai)}{
};
如果您不想独占Q对A的所有权,或者不想提供虚拟析构函数,也可以使用
std::shared_ptr
。共享指针动态地记住存储的类,因此如果它们被正确地创建,就可以正确地销毁对象,特别是使用
std::make_Shared
。此外,它们还使用引用计数,只有在对象的所有引用都消失后才会删除该对象。
缺点是,与std::unique\u ptr相比,std::unique\u ptr通常没有普通指针的开销。容器必须包含指向基类型的指针,才能提供多态功能。例如一个
std::unique\u ptr
。在类
Q
中,你应该有一个指向
a
的智能指针,不要忘记。你的代码仍然无效,除非
foo
void
的别名,我认为警告是因为缺少
return
语句。可能需要谨慎地指出
std::unique\u ptr
具有未定义的行为,除非将
~A
修改为虚拟。@user2079303:谢谢,这是正确的,我编辑了答案。附加说明,可能有点离题:通过声明虚拟析构函数,隐式移动构造函数/赋值将被抑制,并且复制操作将用于移动。如果
A
B
C
包含复制速度慢但移动速度快的成员,则这是非常不可取的。由于C++11,一个很好的经验法则是每当声明析构函数时总是声明默认的移动操作。@user207933当计划以多态方式使用B和C的对象并通过智能指针动态管理这些对象时,唯一明智的做法是禁用这些类的移动和复制,以及使用这些类的移动和复制相反,指针。@ÖTiib禁用类的移动将是愚蠢的。有效地实现这一点很简单,而且非常有用。复制将通过具有唯一指针成员而自动禁用,我同意无需特意实现它。共享ptr不是为拥有而设计的,而是为共享所有权而设计的。大量使用is作为拥有智能指针是一种初步的悲观情绪,这使得许多代码毫无意义地低效。@ÖöTiib不是真的。共享指针实际上是为拥有而设计的。更具体地说是共享的。当然,这可能会有点慢,这取决于用例,但这也是拥有一个缺少虚拟析构函数的多态对象的最简单的方法。在不需要共享所有权的情况下使用shared_ptr只是令人困惑。将虚拟析构函数始终添加到多态类。现代编译器尽可能避免通过vtable调用它。它只是使层次结构更加可靠。进一步的分析表明,Q需要的不是一个A,而是A的集合。所以程序员接受boost::ptr_向量,但忘记检查A的析构函数是虚拟的,并且具有未定义的行为。