简体   繁体   中英

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. 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. However, you can store a pointer to P as a member of class A ; this pointer member could then point to an instance of a (concrete) subclass of P .

No. A composition relationship implies that class Client actually contains a member variable of type 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:2: note: because the following virtual functions are pure within 'abstract':
prog.cpp:3: note: virtual void abstract::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.

If you have access to the book, see item 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. So calling A's "say_hello()" will end up printing "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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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