简体   繁体   English

抽象类是否可以作为其他具体类的成员构成关系? C ++

[英]Can an abstract class be member of other concrete class as composition relationship ? c++

P is an abstract class, I want to make it member of class A which is a normal concrete class. P是抽象类,我想使其成为A类的成员,而A类是普通的具体类。 Is it possible if yes how. 如果可以,有可能吗。 Relationship is composition Thanks for help 关系是组成谢谢您的帮助

Since P is abstract, you can never create an object of that type. 由于P是抽象的,因此您永远无法创建该类型的对象。 However, you can store a pointer to P as a member of class A ; 但是,您可以将指向P的指针存储为类A的成员; this pointer member could then point to an instance of a (concrete) subclass of P . 然后,此指针成员可以指向P (具体)子类的实例。

No. A composition relationship implies that class Client actually contains a member variable of type AbstractClass. 否。组成关系意味着Client类实际上包含类型AbstractClass的成员变量。

I'm assuming your definition of "abstract class" is the common one of a class with at least one pure virtual function. 我假设您对“抽象类”的定义是具有至少一个纯虚函数的类的常见定义。 That means it cannot be a member of a concrete class because that class would not be able to be instantiated. 这意味着它不能成为具体类的成员,因为该类不能被实例化。

You can have a reference or pointer to an abstract class including one where lifetime is managed for you much like a composition relationship, eg: 您可以具有一个抽象类的引用或指针,该类包括一个为您管理生命周期的抽象类,例如组成关系,例如:

   class Client {
    public:
      Client(AbstractClass* adopted) : ownedAbstract(adopted) {}
    ...
    std::shared_ptr<AbstractClass> ownedAbstract;

   };

   class AbstractClass{
    public:
      virtual ~AbstractClass()=0;  // virtual dtor needed so can delete AbstractClass*    
   };       

   class AbstractSubclass : public AbstractClass{
    public:
      virtual ~AbstractSubclass();
   };


   Client fred(new AbstractSubclass);

You cannot create any objects of an abstract class. 您不能创建抽象类的任何对象。 so you cannot do this. 所以你不能这样做。
You can however have a class member which is pointer to the abstract class. 但是,可以有一个指向抽象类的指针的类成员。

Here is a code sample to prove it to: 是一个代码示例,以证明这一点:

class abstract
{
   virtual void somethiing() = 0;
};

class concrete
{
    abstract obj;

};
int main()
{
    return 0;
}

Compilation: 汇编:

prog.cpp:8: error: cannot declare field 'concrete::obj' to be of abstract type 'abstract' prog.cpp:8:错误:无法声明字段'concrete :: obj'为抽象类型'abstract'
prog.cpp:2: note: because the following virtual functions are pure within 'abstract': prog.cpp:2:注意:因为以下虚拟函数在“抽象”中是纯函数:
prog.cpp:3: note: virtual void abstract::somethiing() prog.cpp:3:注意:虚空抽象:: somethiing()

Compilable sample: 编译样本:

class abstract
{
   virtual void somethiing() = 0;
};

class concrete
{
    abstract *ptr;

};
int main()
{
    return 0;
}

You may not instantiate the abstract class explicitly within another class. 您不能在另一个类中显式实例化抽象类。 But you may give an abstract base class's pure virtual functions a definition which may in turn be invoked in a derived class in a way that feels a lot like composition. 但是,您可以为抽象基类的纯虚函数提供一个定义,该定义又可以在派生类中以与组合非常相似的方式调用。

Effective C++ Programming (second edition) suggests that the reason that pure virtual functions in abstract classes can have a body (definition) is because an inheriting class may provide an implementation of the function that invokes the pure virtual version within its body. 有效的C ++编程(第二版)表明,抽象类中的纯虚函数可以具有主体(定义)的原因是因为继承类可以提供在其主体内调用纯虚版本的函数的实现。

If you have access to the book, see item 36. 如果您有权使用该书,请参阅第36条。

Here's an example I cobbled together. 这是我拼凑的一个例子。 It demonstrates how a form of object composition can be achieved by inheriting the interface from an abstract class and using its implementation to compose the implementation of the function's definition in the derived class. 它演示了如何通过从抽象类继承接口并使用其实现在派生类中构成函数定义的实现来实现一种对象组合形式。

#include <iostream>

class P {
  public:
    virtual void say_hello() = 0;
};

void P::say_hello() { std::cout << "Hello world!" << std::endl; }

class A :public P {
  public:
    void say_hello() { P::say_hello(); }
};

int main() {
    A x;
    x.say_hello();
    return 0;
}

The result will be that class A's 'say_hello' will invoke P's pure-virtual version of the function by the same name. 结果将是类A的“ say_hello”将使用相同的名称调用P的函数的纯虚拟版本。 So calling A's "say_hello()" will end up printing "Hello world." 因此,调用A的“ say_hello()”将最终显示“ Hello world”。

Public and protected member data in the abstract class is also available to the derived class. 抽象类中的公共和受保护成员数据也可用于派生类。

#include <iostream>
#include <string>

using namespace std;

class P {
  public:
    P() { audience = "world"; }
    virtual void say_hello() = 0;
  protected:
    string audience;
};

void P::say_hello() { cout << "Hello " << audience << "!" << endl; }

class A :public P {
  public:
    void say_hello() { P::say_hello(); }
    void say_goodbye() { cout << "Goodbye " << audience << "." << endl; }

};

int main() {
    A x;
    x.say_hello();
    x.say_goodbye();
    return 0;
}

I understand this sounds asymmetrical but the answer is no. 我了解这听起来不对称,但答案是否定的。 An abstract class cannot be instantiated and therefore cannot be used as a member of another class. 抽象类无法实例化,因此不能用作另一个类的成员。

The asymmetry is evident because you can use an abstract class as base, and even the base subobject of an object must be instantiated; 这种不对称是显而易见的,因为您可以将抽象类用作基类,甚至必须实例化对象的基类子对象。 but in this case the operation is permitted and simply the resulting class automatically becomes abstract. 但是在这种情况下,该操作是允许的,并且简单地将结果类自动变为抽象。

The logical reason is however that in this last case you will be able to derive from this new abstract class a concrete class, while in the former case there would be no way with the C++ language syntax to later substitute an included object type with an object of a class derived from that type. 但是,合乎逻辑的原因是,在后一种情况下,您将能够从这个新的抽象类派生出一个具体的类,而在前一种情况下,C ++语言语法将无法用一个对象来替换一个包含的对象类型。从该类型派生的类。

In a sense the type of the/a base subobject of a class can be later modified down in the inheritance hierarchy, while the type of a regular member subobject is fixed. 从某种意义上说,可以稍后在继承层次结构中向下修改类的基础子对象的类型,而固定成员子对象的类型是固定的。

You can of course use a pointer or a reference to an abstract class in an object, because in this case the real type of the object will be concrete and will be known only at runtime. 您当然可以在对象中使用指向抽象类的指针或引用,因为在这种情况下,对象的实际类型将是具体的,并且仅在运行时才知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM