Override is quite informative keyword. However, one can use it in class declaration only. Is there any reason to forbid its use in definitions? Example:
class Base
{
public:
virtual void Method() = 0;
};
class Child : public Base
{
public:
void Method() override;
};
// source.cpp
void Child::Method() override // oops
{
...
}
Related
I have a class hierarchy like this:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/};
};
class Special : public Default
{
private:
virtual void init() override final {/*specialized implementation*/};
}
Which works alright if I call start() on an object of type Special;
Now I have a case where in the implementation in the Special class I want to call the implementation of the Default class.
Normally that would work with Default::init();, but will fail here due to the Defaults declaration of this is private.
Obviously one solution is to change this from private to protected, but I'd like to ask if there is another way? Rather than allowing any child to call this function directly, I'd like to limit this to calls that are initiated via virtual functions already defined in the Base or Default class.
Is there some option or modifier that would allow member function calls to be only allowed from child classes if they are within (the same) overriding virtual member functions?
C++ doesn't provide means to achieve this directly, so you'd have to work around, e. g. in piece of code below.
Well, if you absolutely want to. I personally would rather just fall back to making the functions protected, document what they are intended for and when to be called, and then just trust the deriving classes to do the stuff right. That in the end keeps the interfaces cleaner and doesn't rely on a rather unusual (and perhaps ugly) pattern (actually passing this twice).
class Base
{
public:
virtual ~Base() { }
void start()
{
InitProxy p(*this);
init(p);
}
protected:
class InitProxy
{
public:
InitProxy(InitProxy const&) = delete;
void init()
{
m_base.Base::init(*this);
}
private:
friend class Base;
Base& m_base;
InitProxy(Base& base)
: m_base(base)
{ }
};
private:
virtual void init(InitProxy& proxy) { }
};
class Derived : public Base
{
void init(InitProxy& proxy) override
{
proxy.init();
}
};
You could let the proxy accept a member function pointer, if you want to apply this constraint to more than one function, so you wouldn't have to re-write the proxy for every function separately. Possibly you'd need to make a template from then, if function parameters differ.
Forward declare Special, and make it a friend of Default:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Special; // Forward declaration
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/}
friend class Special; // Friend declaration
};
class Special : public Default
{
private:
virtual void init() override final {
Default::init();
/*Other implementation*/
}
};
What I want to do
I want to have a base interface and a lot of sub interface extenting this base interface
I want a default implementation of the default interface
I want that all my sub interface implementations extend the default implementation and only override those methods they want
I have defined following public interfaces - those are needed this way for the SDK I develop plugins for
// the base interface
class DYNAMIC_ATTRIBUTE IMasterProfile : public IVWUnknown
{
public:
virtual Uint16 VCOM_CALLTYPE GetNodeVersion() = 0;
// ...
}
// one of many sub interfaces extending the default one
class DYNAMIC_ATTRIBUTE ISomeProfile : public IMasterProfile
{
public:
virtual void VCOM_CALLTYPE SwapData() = 0;
};
My implementation looks like following:
class DYNAMIC_ATTRIBUTE MasterProfile : public virtual IMasterProfile
{
public:
Uint16 VCOM_CALLTYPE GetNodeVersion() override { return 0; };
// ...
}
class DYNAMIC_ATTRIBUTE SomeProfile : public MasterProfile, public virtual ISomeProfile
{
public:
void VCOM_CALLTYPE SwapData() override { }
}
Problems:
The compiler complains that SomeProfile is abstract and has not implemented GetNodeVersion function. How can I solve this? SomeProfile is extenting MasterProfile and this class is implementing the GetNodeVersion function...
EDIT: Possible solution
I can move the IMasterProfile default implementation into the header and everything works (additionally I remove the virtual inheritance). I am curious if this can be solved without moving the default implemention into the header...
The problem is with ambiguity. You must implement GetNodeVersion in ISomeProfile. Otherwise SomeProfile::ISomeProfile::GetNodeVersion is not defined and it's abstract.
Consider this code:
class IMasterProfile
{
public:
virtual int GetNodeVersion() = 0;
};
class ISomeProfile : public IMasterProfile
{
public:
virtual void SwapData() = 0;
int GetNodeVersion() override { return 2; };
};
class MasterProfile : virtual IMasterProfile
{
public:
int GetNodeVersion() override { return 3; };
// ...
};
class SomeProfile : public MasterProfile, public virtual ISomeProfile
{
public:
SomeProfile(){ std::cout<<ISomeProfile::GetNodeVersion();}
void print()
{
std::cout<<GetNodeVersion(); // ERROR: Call to the "GetNodeVersion" is ambiguous
std::cout<<MasterProfile::GetNodeVersion(); // Call to the GetNodeVersion from MasterProfile
std::cout<<ISomeProfile::GetNodeVersion(); // Call to the GetNodeVersion from ISomeProfile, without implementing it's virtual method
}
void SwapData() override { }
};
So the problem is line, when you want use in SomeProfile:
std::cout<<ISomeProfile::GetNodeVersion(); // Call to the GetNodeVersion from ISomeProfile, without implementing it's virtual method
Without implementation you can't do it, a definition is needed.
I have two classes with the same pure virtual method:
class InterfaceA
{
public: virtual void doSomething() = 0;
};
class InterfaceB
{
public: virtual void doSomething() = 0;
};
And I have a class that derives from these interfaces. I want to override
each virtual function. I can do it this way (this works):
class ConcreteClass : public InterfaceA, public InterfaceB
{
public:
void InterfaceA::doSomething() override
{
printf( "In ConcreteClass::InterfaceA::doSomething()\n" );
}
void InterfaceB::doSomething() override
{
printf( "In ConcreteClass::InterfaceB::doSomething()\n" );
}
};
My question is however, how can I have my methods' definitions outside the class declaration? So I can have them in my .cpp file. I tried this first:
// .h
class ConcreteClass : public InterfaceA, public InterfaceB
{
public:
void InterfaceA::doSomething() override;
void InterfaceB::doSomething() override;
};
// .cpp
void ConcreteClass::InterfaceA::doSomething()
{
printf( "In ConcreteClass::InterfaceA::doSomething()\n" );
}
void ConcreteClass::InterfaceB::doSomething()
{
printf( "In ConcreteClass::InterfaceB::doSomething()\n" );
}
This doesn't compile in Visual C++ 2005 (VS 2005):
error C2509: 'doSomething' : member function not declared in 'ConcreteClass'
Does it require a specific sintax in order to be compiled?
Microsoft's MSDN documentation has a working example. But they use their __interface extension. I want to achieve the same but code that complies with standard c++03, if it is even possible.
Thanks!
Even though it's not exactly what you are looking for, the obvious workaround is to dispatch to helper functions:
class ConcreteClass : public InterfaceA, public InterfaceB
{
public:
void InterfaceA::doSomething() override {
InterfaceA_doSomething();
}
void InterfaceB::doSomething() override {
InterfaceB_doSomething();
}
private:
void InterfaceA_doSomething();
void InterfaceB_doSomething();
};
I have encountered a virtual method in a nested class.
##classone.h
class ClassOne: {
public:
class InnerClass{
public:
virtual void method1();
...
##classone.cpp
void ClassOne::InnerClass::method1()
{
...
}
I am subclassing ClassOne and need to extend method1(). What need's to be done with the nested class in that situation?
What I tried
##subclassone.h
class SubClassOne: public ClassOne{
public:
virtual void method1();
##subclassone.cpp
void SubClassOne::InnerClass::method1()
{
##New implementation
}
But that gives a multiple definition of ClassOne::InnerClass::method1()
method1 belongs to ClassOne::InnerClass, not ClassOne. When you inherit from ClassOne, the nested class from base class becomes a member of the derived class, too, and you can reach it by qualifying with either ClassOne:: or SubClassOne::. Hence the double definition error regarding method1.
You'll need to sub-class InnerClass, too. If you still wish to derive from ClassOne, it would look like this:
class ClassOne {
public:
class InnerClass {
public:
virtual void method1();
};
};
void ClassOne::InnerClass::method1()
{
}
class SubClassOne : public ClassOne {
class DerivedInnerClass : InnerClass { //
virtual void method1();
};
};
void SubClassOne::DerivedInnerClass::method1()
{
}
Please refer the following example.
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1();
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
In the above example, for all other entities deriving from IBase needs to implement BaseMethod1() and BaseMethod2().Because of which lots of code duplication is happening? Is there anyway where we can avoid redundant implementation of IBase methods in entities deriving from it?
You can use virtual inheritance in combination with a default base implementation class to encapsulate your default base behavior, and have it be only inherited by the concrete classes you want, like follows:
using namespace std;
//Base interface
class IBase
{
public:
virtual void BaseMethod1() = 0;
virtual void BaseMethod2() = 0;
};
class IEntity1 : virtual public IBase
{
public:
virtual void Entity1Method1() = 0;
virtual void Entity1Method2() = 0;
};
class BaseImpl : virtual public IBase
{
public:
virtual void BaseMethod1()
{
...
}
virtual void BaseMethod2()
{
...
}
}
class Entity1 : public IEntity1, public BaseImpl
{
public:
Entity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
There is, however, a runtime cost associated with virtual inheritance. Multiple inheritance also comes with some structural issues, e.g. base class construction.
You can even have some fun with template classes to make your class composition more modular:
template<typename TEntity, typename TBaseImpl>
class ConcreteEntity: public TEntity, public TBaseImpl
{
public:
ConcreteEntity() {}
};
class ConreteEntity1 : public ConcreteEntity<IEntity1, BaseImpl>
{
public:
ConreteEntity1();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//ConreteEntity1 Methods
void Method1();
void Method2();
};
You could make a function that is called in BaseMethod1() implementations that are the same.
Something like this:
void BaseMethod1_common();
class Entity1 : public IEntity1
{
public:
Entity();
//IBaseMethods
void BaseMethod1() { BaseMethod1_common(); }
void BaseMethod2();
//IEntityMethods
void Entity1Method1();
void Entity1Method2();
//EntityMethods
void Method1();
void Method2();
};
First of all IBase deserves a virtual destructor.
Declare it pure virtual and define IBase:BaseMethod1() and
IBase::BaseMethod1().
If your intention is to hide implementation, then the only option would be to release the code as a library and then share only the header file among the other developers.
Implementing a global function, or using multiple inheritance as suggested still mean that your implementation is exposed.
However, if the intent is to reduce coupling among the various classes, there's another option :
Create a class that has the actual shared implementation, and then another class which will be an interface to it.
This interface class will then be the base class for other derived entities.
Example code is shown below :
//First Header and Cpp file
class Base_private
{
public:
BaseImpl(arguments);
~BaseImpl();
void BaseMethod1() {
//Implementation
}
void BaseMethod2() {
//Implementation
}
};
//Second Header and Cpp file
class BaseInterface
{
public:
BaseInterface(arguments);
~BaseInterface();
void BaseMethod1() {
m_pBase->BaseMethod1();
}
void BaseMethod2() {
m_pBase->BaseMethod2();
}
private:
Base_private* m_pBase;
};
class Entity : public BaseInterface
{
public:
Entity(arguments);
~Entity();
void Method1();
void Method2();
};