C ++ inheritance with pure virtual functions

I am trying to create a class that serves as a base object, which will then be subclassed (= implemented) to serve various purposes.

I want to define one or more pure virtual functions, so be that as it may, subclasses of the base class are necessary and don't forget to implement them.

There is one caveat, the pure signature of a virtual function includes the type of the base object. After the subclass, the definition of the function, of course, does not match the definition of the base classes. For instance:.

class BaseItem { public: virtual std::string getDifferences(const BaseItem& item) = 0; } 

So, in a derived class, I would like to do:

 class DerivedClass : public BaseItem { public: virtual std::string getDifferences(const DerivedClass& item) = 0; private: std::string derivedItemCustomObject; } 

which, of course, the compiler will not accept. I could do it with BaseItem , of course, but then I cannot use any objects in the derived class.

Should casting be used to accomplish this?

Please let me know if my intention / question is not clear.

+4
source share
5 answers

There is NO to change the signature of the function . See the following:

 class BaseItem {public: virtual std::string getDifferences(const BaseItem& item) = 0; }; class DerivedClass : public BaseItem {public: virtual std::string getDifferences(const BaseItem& item) // keep it as it's { const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item); } }; 

It can use static_cast<> without any fear, because DerivedClass::getDifferences() is called only for the DerivedClass object. To illustrate

 BaseItem *p = new DerivedClass; DerivedClass obj; p->getDifferences(obj); // this always invoke DerivedClass::getDifferences 

If you fear that someday you may pass some other object of the derived class as an argument to the method, use dynamic_cast<> instead and throw an exception if this casting fails.

+3
source

It is not clear what you are trying to achieve. Suppose the compiler allowed you to do this (or you do it by casting), then it will open the following hole in the type system:

 class BaseItem { public: virtual std::string getDifferences(const BaseItem& item) = 0; }; class DerivedClass : public BaseItem { public: virtual std::string getDifferences(const DerivedClass& item) { item.f(); // ... } void f() const {} }; class DerivedClass2 : public BaseItem { public: virtual std::string getDifferences(const DerivedClass2& item) { ... } }; void g() { BaseItem* x = new DerivedClass; // oops, calls DerivedClass::f on an instance of DerivedClass2 x->getDifferences(DerivedClass2()); } 

Your design may be wrong.

+2
source

I assume the compiler accepts, but DerivedClass :: getDifferences does not override BaseItem :: getDifferences. Here's a way to get what you seem to want

 template <typename T> class DerivedHelper: public BaseItem { public: virtual std::string getDifferences(const BaseItem& item) { getDifferences(dynamic_cast<const T&>(item)); } virtual std::string getDifferences(const T& item) = 0; }; class DerivedClass : public DerivedHelper<DerivedClass> { public: // not more needed but providing it will hide getDifferences(const BaseItem& item) // helping to statically catch some cases where a bad argument type is used. virtual std::string getDifferences(const DerivedClass& item) = 0; private: std::string derivedItemCustomObject; }; 

but keep in mind that there is a runtime check that will throw exceptions if the argument does not match the correct class.

+2
source

One way to achieve this is to use a template and specify a type parameter of the derived type

 template <typename T> class BaseItem { public: virtual std::string getDifferences(const T& item) = 0; }; class DerivedClass : public BaseItem<DerivedClass> { public: virtual std::string getDifferences(const DerivedClass& item) { // Implement it here } }; 
+1
source

You should use the cast command from BaseItem in DerivedClass + execution check if the given BaseItem is an instance of DerivedClass.

0
source

All Articles