I have the following interfaces and classes
public interface IBase
{
virtual void SomeBaseMethod()=0;
}
public interface IDerived : IBase
{
virtual void SomeOtherMethod()=0;
}
public class base: public IBase
{
void SomeBaseMethod(){};
}
public class derived: public base, public IDerived
{
void SomeBaseMethod(){};
void SomeOtherMethod(){};
}
In class derived, I have to repeat 'void SomeBaseMethod(){};', which have already implement in my class base. Otherwise I will get compile error. Is it possible not repeat 'void SomeBaseMethod(){};' in my class derived?
Unfortunately, you have to repeat yourself here. C++ has virtual inheritance, which would solve this problem, but you can't use virtual inheritance with COM interfaces. Here's an explanation as to why.
Related
I was wondering what was the best way to achieve code reuse by inheritance in a COM application.
The Problem
It came to my understanding that the virtual inheritance model of C++ cannot by used in a COM environment because it is not language independent.
In pure C++ a class hierarchy could look something like the following:
interface IBase {
virtual void BaseMethod() = 0;
};
interface IDerived : virtual IBase {
virtual void DerivedMethod() = 0;
};
class CBase : public virtual IBase {
public:
virtual void BaseMethod() override { /* Do something */ }
};
class CDerived : public IDerived, public CBase {
public:
virtual void DerivedMethod() override { /* Do something */ }
};
This results in the following hierarchy:
IDerived and CBase both inherit virtually from IBase.
Since virtual inheritance is not available in COM, the class hierarchy would rather look something like this:
interface IBase {
virtual void BaseMethod() = 0;
};
interface IDerived : IBase {
virtual void DerivedMethod() = 0;
};
class CBase : public IBase {
public:
virtual void BaseMethod() override { /* Do something */ }
};
class CDerived : public IDerived, public CBase {
public:
virtual void DerivedMethod() override { /* Do something */ }
};
This results in the following hierarchy:
At first glance, there seems to be a problem with the ambiguity of IBase. This can be easily resolved by implementing the IUnknown::QueryInterface method.
The real problem is, how can CDerived inherit the implemented methods of IBase from CBase, namely CBase::BaseMethod?
In the case of virtual inheritance, CBase::BaseMethod can be inherited by dominance, but without virtual inheritance this cannot happen: In CDerived, the method CBase::IBase::BaseMethod is defined, however the method IDerived::IBase::BaseMethod is not, resulting in the class CBase still being abstract and not thus not eligible for instantiation.
One way, to resolve this would be to override the method BaseMethod in CDerived once again:
class CDerived : public IDerived, public CBase {
public:
virtual void BaseMethod() override { CBase::BaseMethod(); }
virtual void DerivedMethod() override { /* Do something */ }
};
Does this have any performance implications? Is there a better way of achieving what I want? Doesn't the repeated override of the function in CDerived defeat the whole idea of inheritance?
ATL widely uses a technique that goes like this:
template <typename Itf>
class IBaseImpl : public Itf {
public:
void BaseMethod() override;
};
class CBase : public IBaseImpl<IBase> {};
class CDerived : public IBaseImpl<IDerived> {
public:
void DerivedMethod() override;
};
Now you have straight-line inheritance: IBase <- IDerived <- IBaseImpl<IDerived> <- CDerived.
I want to create an abstract class with a pure virtual private method but I can't implement that in my concrete class. My option is to make that pure virtual private method to protected but in my concrete class I want to make it only a private. Like,
class IFoo
{
public:
IFoo(){}
virtual ~IFoo(){}
protected:
virtual void fooMethod() = 0;
};
class Foo : public IFoo
{
public:
Foo(){}
virtual ~Foo(){}
private:
virtual void fooMethod() {}
};
Is there any implication doing this? Or this is just fine?
Thanks!
Why can't you make the method private in the base class? Making them private is a pretty standard design pattern for C++. Then the base class implements public/protected methods that call the private ones.
http://www.gotw.ca/publications/mill18.htm has way more info on the uses of public/private/protected virtual methods.
Lets suppose you want to make an interface of the class Derived and it looks like this:
class Derived : public Base
{
public:
foo();
}
class Base
{
public:
tii();
//many other methods
}
How would you do the Interface? How can you make Base::tii visible (and also other methods) to this new interface?
class IDerived
{
public:
virtual foo() = 0;
// should I declare here tii() as a pure virtual function?
// but by doing it now there is ambiguity!
}
What is a good strategy?
The new Derived class should look like this....
class Derived : public Base, public IDerived
{
//implement the real thing
}
Your example is doing things backwards: the interface should be defined independently of any concrete classes with all pure virtual methods:
class IDerived
{
public:
virtual void foo() = 0;
virtual ~IDerived() {} // don't forget to include a virtual destructor
}
And the concrete classes will derive publicly from the interface:
class Derived : public Base, public IDerived
{
public:
void foo();
}
If you want IDerived to also declare methods that Derived inherits from Base, you can have Derived explicitly implement the method by calling the inherited implementation:
class Derived : public Base, public IDerived
{
public:
void foo();
void bar() { Base::bar(); }
}
At front, I dislike interfaces (they are grown by other languages than c++).
Anyway, if you have one, it should be complete: Hence have the 'tii() as a pure virtual function'. To resolve the conflict rewrite that function in 'Derived' (forward to Base::tii).
I have the following code:
class Interface
{
virtual void method()=0;
};
class Base : public Interface
{
virtual void method()
{
//implementation here
}
};
class Parent: public Interface
{
};
class Child : public Base, public Parent
{
};
int main()
{
Child c;//ERROR: cannot instantiate abstract class
}
Now I know why this is happening, since I'm inheriting Parent then I have to implement method again. But it's already defined in Base class and I don't want to override that definition for every child class. I think there was some standard way of getting rid of this in c++ (telling compiler which copy of Interface should it use) I just can't remember what it was.
What you are talking about is called dominance.
From the linked article:
class Parent
{
public:
virtual void function();
};
class Child1 : public virtual Parent
{
public:
void function();
};
class Child2 : public virtual Parent
{
};
class Grandchild : public Child1, public Child2
{
public:
Grandchild()
{
function();
}
};
You have a diamond-shaped hierarchy but are not using virtual inheritance.
As a result, you end up with two distinct virtual method() functions in your Child class.
One way to fix it is to move to using virtual inheritance. This way you'll only have a single Child::method() and won't need two implementations.
Pure virtual functions must be defined in the derived class.
If you don't do so, your derived class (in this case "child") will itself become an abstract class which can't be instantiated and hence the error.
I am trying to define interface types in C++ using abstract classes and implement them with concrete classes. The problem I am running into is that I cannot both inherit and interface from another interface and inherit the implementation from a base concrete class.
My goal is to be able to define a hierarchy of interfaces which may inherit from less complex base interfaces. I also want to be able to extend the implementation of interfaces by inheriting from concrete classes (like inheriting from TObjectA in the example below).
This is what I have. The error I am getting is "object of abstract class type "TObjectB" is not allowed". I believe I know why, which is because I didn't implement MethodA() in TObjectB. But I really want is to have the implementation provided by a base class (TObjectA) and still have interface hierarchies (IInterfaceB inherits from IInterfaceA). I also don't want to repeat all the inherited interface methods in my derived concreate classes. How can I do this?
class IInterfaceA
{
public:
virtual void MethodA() = 0;
};
class IInterfaceB : IInterfaceA
{
public:
virtual void MethodB() = 0;
};
class TObjectA : public IInterfaceA
{
public:
void MethodA() { cout << "Method A"; }
};
class TObjectB : public TObjectA, public IInterfaceB
{
public:
void MethodB() { cout << "Method B"; }
};
void TestInterfaces()
{
IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed
b->MethodB();
delete b;
}
In your class hierarchy, TObjectB actually has two IInterfaceA base class subobjects: one inherited through IInterfaceB and one inherited through TObjectA. The MethodA() from each of them needs to be implemented.
You need to inherit from the interface classes using public virtual inheritance, which ensures there is only a single base class subobject of each interface class type:
class IInterfaceA
{
public:
virtual void MethodA() = 0;
};
class IInterfaceB : public virtual IInterfaceA
{
public:
virtual void MethodB() = 0;
};
class TObjectA : public virtual IInterfaceA
{
public:
void MethodA() { cout << "Method A"; }
};
class TObjectB : public TObjectA, public virtual IInterfaceB
{
public:
void MethodB() { cout << "Method B"; }
};
void TestInterfaces()
{
TObjectB b_object;
IInterfaceB& b = b_object;
b.MethodB();
}
Whether or not such complex class hierarchies are desirable is another matter altogether.
Your problem is caused by the dreaded diamond inheritance. You've implemented TObjectA::IInterfaceA::MethodA but not IInterfaceB::IInterfaceA::MethodA.
My recommendation would be to make IIterfaceA and IIterfaceB completely independent. If that's not possible, you can look into virtual inheritance.