Reputation:
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
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
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
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
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
}
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