user7972945
user7972945

Reputation:

Method of Abstract Class used by derived Class

I got an Abstract Baseclass which looks like this:

class AbstractClass {
public:
    virtual ~AbstractClass() = 0 {}
    std::string GetName() const { return m_Name; }
private:
    std::string m_Name;
};

Now I got many derived Classes and I want to implement them like this

class DerivedClass1 : public AbstractClass{
public:
    DerivedClass1() = default;
    ~DerivedClass1() = default;
private:
    std::string m_Name = "DerivedClass1";
};


int main() {
    DerivedClass1 class1;
    std::cout << class1.GetName();

    return 0;
}

I dont want to override GetName() everytime i derive a Class, is this possible? Edit: I got a Linker Error. Error LNK2019.

Upvotes: 0

Views: 92

Answers (4)

Marek R
Marek R

Reputation: 37607

Code sugest that problem is how to get a class name? But this is not clearly stated in question (XY problem)

How to handle class name?

You can use RTTI:

class ClassName {
public:
    virtual ~ClassName() {} // just to enable RTTI for all decendants

    std::string getClassName() {
        return typeid(*this).name();
    }
};

https://wandbox.org/permlink/LvPdA37arMr0LFQW

But as you can see it adds some extra prefix (it is compiler depended). boost can clean it up:

https://wandbox.org/permlink/8XiB7yVOM0wYVxpl

Upvotes: 0

Hatted Rooster
Hatted Rooster

Reputation: 36463

That's not how you "override" GetName(). You can either make GetName() virtual and override it in your derived classes:

class AbstractClass {
public:
   virtual ~AbstractClass() = default;
   virtual std::string GetName() const { return "AbstractClass"; }
private:
   std::string m_Name;
};

and:

class DerivedClass1 : public AbstractClass {
public:
   DerivedClass() = default;
   std::string GetName() const override { return "DerivedClass1"; }
};

Or you can set m_Name in your derived classes by passing it to the base class constructor:

class AbstractClass {
public:
   AbstractClass(const std::string& name) : m_Name(name) {}
   virtual ~AbstractClass() = default;
   std::string GetName() const { return m_Name; }
protected: // protected not private
   std::string m_Name;
};

and:

class DerivedClass1 : public AbstractClass {
public:
   DerivedClass() : AbstractClass("DerivedClass1") {}
};

Or you can set it in the derived's class constructor:

class AbstractClass {
public:
   virtual ~AbstractClass() = default;
   std::string GetName() const { return m_Name; }
protected: // protected not private
   std::string m_Name;
};

and:

class DerivedClass1 : public AbstractClass {
public:
   DerivedClass() : AbstractClass() { m_Name = "DerivedClass1"; }
};

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66371

Use only one name, in the base class, and a constructor with a parameter:

class AbstractClass{
public:
   AbstractClass(const std::string& name) : m_Name(name){}
   std::string GetName() const { return m_Name; }
private:
   std::string m_Name;
};



DerivedClass1 : public AbstractClass{
public:
   DerivedClass() : AbstractClass("DerivedClass1") {}
};


int main(){
   DerivedClass1 class1;
   std::cout << class1.GetName();

    return 0;
}

There seems to be no reason for making the base class abstract, but if you do need that, even a pure virtual destructor must have a definition, or you will get a linker error, because it's needed when destroying derived objects.
Also, if the destructor didn't exist, when would m_Name be destroyed?

class Abstract
{
public: 
    virtual ~Abstract() = 0;
};

Abstract::~Abstract() {}

This makes a class that can't be instantiated, but whose derived classes can still be destroyed.

Upvotes: 2

Davide Spataro
Davide Spataro

Reputation: 7482

You get the link error because the destructor for AbstractClass needs to be defined even if it is empty.

AbstractClass::~AbstractClass()
{
  // Compulsory virtual destructor definition,
  // even if it's empty
}

LIVE on Wandbox

Regarding overriding getName: you do not have to. If you do not provide an implementation in the derived class, the one inherited one is used.

Upvotes: 0

Related Questions