I've posted about this problem before (Here), this is a different approach to a solution. This solution to be seems to better encapsulate the behavior for those implementing the class, since it prevents them from needing to explicitly up cast.
Here's the problem:
I have a project in which I want to isolate core behavior in most objects, while providing additional behavior through derived objects. Simple enough:
class BaseA
{
virtual void something() {}
}
class DerivedA : public BaseA
{
void something() {}
void somethingElse() {}
}
Now let’s say I also have a second set of classes, same inheritance scheme except that they aggregate the above classes. However, I would like the base version to use the base class, and the derived version in the derived class. My solution i was thinking about 'hiding' the base class variable by using the same name;
class BaseB
{
BaseA *var;
BaseB()
{
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
}
class DerivedB : public BaseB
{
DerivedA *var;
DerivedB()
{
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
}
The goal for this approach is so that functions that rely on the derived aggregated class no longer need to explicitly cast to achieve the gained functionality.
void func1( BaseB &b )
{
b.anotherThing1();
b.var->something();
}
void func2( DerivedB &b )
{
b.anotherThing1();
b.andAnother1();
b.var->something();
b.var->somethingElse();
}
void main( int argc, char **argv )
{
BaseB baseB;
DerivedB derivedB;
func1( baseB );
func1( derivedB );
func2( derivedB );
}
Would this be considered bad practice?
Would this be considered bad practice?
Yes, it would be bad practice, because the var in the Base would be unused. It does not look like DerivedB should be deriving from BaseB: instead, they should be derived from the same abstract base class, like this:
class AbstractB {
public:
virtual void anotherThing1() = 0;
virtual void anotherThing2() = 0;
virtual void anotherThing3() = 0;
};
class DerivedB1 : public AbstractB { // Former BaseB
BaseA *var;
public:
DerivedB1() {
var = new BaseA();
}
virtual void anotherThing1();
virtual void anotherThing2();
virtual void anotherThing3();
};
class DerivedB2 : public AbstractB { // Former DerivedB
DerivedA *var;
public:
DerivedB2() {
var = new DerivedA();
}
void anotherThing1();
void anotherThing2();
void anotherThing3();
void andAnother1();
void andAnother2();
};
General principle in use here is that you should try making all your non-leaf classes in your inheritance hierarchy abstract.
Related
Let's see the following C++ codes.
Each inherited class has its member variables and initialization function.
These member variables are some different(almost same type) between inherited classes.
Is there any good way to move (or merge) this initialization into base class?
class Base {
public:
virtual init() = 0;
}
class A: public Base {
public:
int a1;
void init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
void init() { b1 = 1;}
}
No. Base has no knowledge of A::a1 or B::b1. More importantly it should not have any knowledge of it's subclass members as this leads to a fundamental breakdown of the encapsulation you're trying to achieve in the first place.
The best you can do is have your Base class define a virtual method for initialisation and control when that method is called. It is up to each subclass to override the method and ensure that when initialisation is needed it is performed according to each subclass's respective requirements.
One thing to note is that if your initialisation is intended to be once-off for the lifetime of each object, the the correct place to do this is using constructors as per koizyd's answer.
On a related note, I'd like to point out that what you're asking is a variation on one of the most common OO design flaws I've seen in my career.
Using inheritance for code reuse not encapsulation.
Basically you're trying to push functionality into the base class (for reuse), and all this really achieves is making the Base class large, top-heavy and unmaintainable.
In C++ we can't (almost always) create function init, we use constructors
e.g
class Base {
};
class A : public Base {
public:
int a1;
A():Base(), a1(0) {}
};
class B : public Base {
public:
int b1;
B():Base(), b1(1){}
};
Construct "child" is A():Base(),a1(0), it's initializer list (:Base(),a1(0)), which create Base object, and int b1.
You should remember about ; after class.
I'd probably structure code like this:
class Base {
public:
void init() { sub_init(); }
protected:
virtual void sub_init() = 0;
}
class A: public Base {
public:
int a1;
protected:
void sub_init() { a1 = 0;}
}
class B: public Base {
public:
int b1;
protected:
void sub_init() { b1 = 1;}
}
The alternative of doing something like (syntax probably not correct...):
class Base {
public:
virtual void init() = 0;
protected:
void generic_init<T>(T &foo, T const &bar) { foo = bar; }
}
class A: public Base {
public:
int a1;
void init() { generic_init<int>(a1, 0); }
}
class B: public Base {
public:
int b1;
void init() { generic_init<int>(b1, 1); }
}
Looks awful to me!
Maybe you could use the template class skills to solve the problem. Like:
template <typename T> class Base {
public :
virtual void init( T t ) = 0;
};
class A: public Base<T> {
public:
T a1;
void init( T t ) { a1 = t;}
}
class B: public Base<T> {
public:
T b1;
void init( T t ) { b1 = t;}
}
You could have a try.
I have a homework for my programming course that asks me to designs an abstract from whom derive two classes, and from those two derived classes derives another class.
This brings the Deadly Diamond of Death problem. Which can be solved by virtual inheritance, though I need instance the objects of my first two classes to a pointer of my abstract class. And this can't be done with any kind of virtual inheritance. So, if there is a way to specify the base class from which the multiple inheritance class will derive, it would be astronomically useful.
Example:
#include <iostream>
using namespace std;
class Base {
public:
virtual void foo(){};
virtual void bar(){};
};
class Der1 : public Base {
public:
virtual void foo();
};
void Der1::foo()
{
cout << "Der1::foo()" << endl;
}
class Der2 : public Base {
public:
virtual void bar();
};
void Der2::bar()
{
cout << "Der2::bar()" << endl;
}
class Join : virtual Der1, virtual Der2 {
private:
int atribb;
};
int main()
{
Base* obj = new Join();
((Der1 *)(obj))->foo();
}
Compiler error:
nueve.cpp: In function ‘int main()’:
nueve.cpp:43:30: error: ‘Base’ is an ambiguous base of ‘Join’
Base* obj = new Join();
Use virtual inheritance.
class Der1 : public virtual Base {
public:
virtual void foo();
};
class Der2 : public virtual Base {
public:
virtual void bar();
};
If virtual is declared while deriving from base class, as shown in below example, the most derived class object contains only one base class sub object, which helps in resolving the ambiguity in your case.
After doing some code changes, your final executable code:
Code changes in below sample:
Added vitual key word, while deriving the child classes.
Removed "virtual" keyword while deriving most derived class.
Modified main to invoke the member function properly.
#include <iostream>
using namespace std;
class Base {
public:
virtual void foo(){};
virtual void bar(){};
};
class Der1 : public virtual Base {
public:
virtual void foo();
};
void Der1::foo()
{
cout << "Der1::foo()" << endl;
}
class Der2 : public virtual Base {
public:
virtual void bar();
};
void Der2::bar()
{
cout << "Der2::bar()" << endl;
}
class Join : public Der1, public Der2 {
private:
int atribb;
};
int main()
{
Base* obj = new Join();
obj->foo();
}
It's not clear what you're asking for, although you seem to be saying that virtual inheritance from Base is not suitable. So, assuming that's correct, you can replace Base* obj = new Join(); with Base* obj = (Der1*)new Join(); and you'll get a pointer to the Base object that's the base of Der1. Similarly, you can replace it with Base* obj = (Der2*)new Join(); and you'll get a pointer to the Base object thats the base of Der2.
Must virtual methods be always implemented in derived class?
Can I write something like this?
<!-- language: lang-cpp -->
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface();
};
class Derived : public BaseInterface
{
void fun_a() { ... };
};
class FinalClass : public Derived
{
void fun_b() { ... };
}
int main()
{
FinalClass test_obj;
test_obj.fun_a(); // use Derived implementation or fail ???
test_obj.fun_b(); // use own implementation
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a(); // fail or ok ???
test_interface->fun_b();
}
Is the code above correct?
Does another virtual method outflank exist?
Pure virtual methods always must be reimplemented in derived class?
Actually a derived class which is going to be instantiated.
In your code, you didn't make an object from Derived so it's OK.
Can i write something like this?
Yes.
You had some minor errors that I corrected them:
class BaseInterface
{
public:
virtual void fun_a() = 0;
virtual void fun_b() = 0;
virtual ~BaseInterface() {}; // You forget this
};
class Derived : public BaseInterface
{
public:
void fun_a() {} // This should be public as its base
};
class FinalClass : public Derived
{
public:
void fun_b() {} // This should be public as its base
};
int main()
{
FinalClass test_obj;
test_obj.fun_a();
test_obj.fun_b();
BaseInterface* test_interface = new FinalClass();
test_interface->fun_a();
test_interface->fun_b();
}
It makes Derived also an abstract class which you cannot instantiate, seeing you don't implement all the virtual functions from it's base, it becomes an abstract class you cannot directly instantiate.
See here: liveworkspace.org/code/6huYU$10
For the rest, your code should work.
Code is correct.
There is no special concept for interface in C++. All are classes. Some of the class methods can be pure virtual. It only means that compiler cannot create an instance of such class.
it's pretty diffecult for me to describe my problem.
I have two classes, I would say Base_A and Derived_A. You can see from the names, the class Derived_A is derived from Base_A. Also in my program I have other two classes Base_B and Derived_B (also with inheritance). The class Base_A contains the object of Base_B, and the class Derived_A contains the object of Derived_B.
class Base_A {
public:
Base_A() {}
virtual ~Base_A() {}
Base_B b_;
Base_B* pointer_;
void init() {
b_ = Base_B();
pointer_ = &b_;
pointer_->setValue(1);
}
void print() {
pointer_->getValue();
}
};
class Derived_A: public Base_A {
public:
Derived_A() {}
virtual ~Derived_A() {}
Derived_B b_;
Derived_B* pointer_;
void init() {
b_ = Derived_B();
pointer_ = &b_;
pointer_->setValue(2);
pointer_->increaseValue();
}
};
class Base_B {
public:
Base_B() {}
virtual ~Base_B() {}
int value_;
void setValue(int value) {
value_ = value;
}
void getValue() {
cout << "Base_B: " << value_ << endl;
}
};
class Derived_B: public Base_B {
public:
Derived_B() {}
virtual ~Derived_B() {}
void increaseValue() {
value_++;
}
};
int main() {
Derived_A derived_A = Derived_A();
derived_A.init();
derived_A.print();
return 0;
}
How you can see every class of A has one object of class B and pointer to this object. My problem is, when I call the function print(), it does not take Derived_B* pointer_, but try to access Base_B* pointer_, which is not exist. How I can say in my program, that it should take the pointer according to the class? Or do I need to declarate the Base_B* pointer_ inside the Derived_A class like:
Base::pointer_ = pointer_;
Maybe is there other method or algorithm for my problem?
Thank you a lot.
"but try to access Base_B* pointer_, which is not exist"
If DerivedA does not properly initialise BaseA, then DerivedA does not meet the "isA" rule for inheritance and the design needs changed. On the face of things:
Don't re-use names in the derived class such as b_, pointer_.
Its just confusing and you gain no value.
Make init() virtual.
Have DerivedA::init() call BaseA::init() explicitly.
Make pointer_ a virtual method.
Note the use of "covariant return types" for the virtual methods.
class BaseA
{
public:
virtual BaseB* pointer() { return &b_; }
// etc.
};
class DerivedA : public BaseA
{
public:
virtual DerivedB* pointer() { return &b_; }
// etc.
};
wouldn't Base_A have a pointer to Base_B if Base_A::init() was ever called?
why wouldn't you init the base class?
Coluld you provide a simple code example? (sorry C++ nube) and how to call a function from the class you are extending?
A bit useful example: :-)
class CImplementation
{
public:
void doFoo();
};
void CImplementation::doFoo()
{
//implementation
}
class IInterface
{
public:
virtual void foo()=0;
};
class DerivedFromImplementationAndInterface : public CImplementation, public IInterface
{
virtual void foo();
};
void DerivedFromImplementationAndInterface::foo()
{
doFoo();
}
//possible usage:
void method(IInterface& aInterface)
{
aInterface.foo();
}
void test()
{
IInterface* d = new DerivedFromImplementationAndInterface;
method(*d);
}
In C++, you can extend multiple classes, it's called multiple inheritance. Most probably this is what you're looking for. Please read a good book about multiple inheritance and C++ (a quick introduction: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr134.htm), because there are many pitfalls and details to pay attention to.
Example for multiple inheritance:
class A { ... };
class B { ... };
class C: public A, public B {}; // C inherits from A and B.
C++ doesn't explicitly have interfaces, the equivalent of an interface in Java is usually implemented with a class having only pure virtual functions (plus constructors, destructor, copy assignment):
#include <iostream>
// interface
class Fooable {
public:
virtual int foo() = 0;
virtual ~Fooable() {}
};
// base class
class Base {
public:
void non_virtual_function() { std::cout << "Base::non_virtual_function\n"; }
virtual void virtual_function() { std::cout << "Base::virtual_function\n"; }
};
// derived class, inherits from both Base "class" and Fooable "interface"
class Derived: public Base, public Fooable {
public:
virtual int foo() {
// call base class function
Base::non_virtual_function();
// virtual call to function defined in base class, overridden here
virtual_function();
}
virtual void virtual_function() {
// call base class implementation of virtual function directly (rare)
Base::virtual_function();
std::cout << "Derived::virtual_function\n";
}
void non_virtual_function() {
// not called
std::cout << "Derived::non_virtual_function\n";
}
};
int main() {
Derived d;
d.foo();
}
Not sure what you're asking:
class A
{
public:
void method();
};
class B
{
public:
void method();
};
class C : public A, public B
{
public:
void callingMethod();
};
void C::callingMethod()
{
// Here you can just call A::method() or B::method() directly.
A::method();
B::method();
}
Note that multiple inheritance can lead to really hard-to-solve problems and I would recommend to only use it when necessary.
The question as stated,
C++ is it possible to make a class extend one class and implement another?
does not make much sense. The answer to that is just "yes". You can derive from any number of classes: C++ fully support multiple inheritance.
So, given that the question as stated isn't really meaningful, it's at least possible that you meant to ask
C++ is it possible to make a class extend one class and thereby implement another?
The answer to this question is also yes, but it's not trivial. It involves virtual inheritance. Which is quite tricky.
Here's an example:
#include <iostream>
void say( char const s[] ) { std::cout << s << std::endl; }
class TalkerInterface
{
public:
virtual void saySomething() const = 0;
};
class TalkerImpl
: public virtual TalkerInterface
{
public:
void saySomething() const
{
say( "TalkerImpl!" );
}
};
class MyAbstractClass
: public virtual TalkerInterface
{
public:
void foo() const { saySomething(); }
};
class MyClass
: public MyAbstractClass
, public TalkerImpl
{};
int main()
{
MyClass().foo();
}
The virtual inheritance ensures that there is only one sub-object of type TalkerInterface in a MyClass instance. This has some counter-intuitive consequences. One is that "inheriting in an implementation" works, and another is that construction of that base class sub-object happens down in each MyClass constructor, and more generally down in the most derived class.
Cheers & hth.,