I have following class hierrachy:
class Base
{
public:
virtual void DoA();
virtual void DoB();
virtual void DoC();
protected:
float m_x;
float m_y;
};
class DerivedA : public Base
{
public:
virtual void DoA() override;
virtual void DoB() override;
virtual void DoC() override;
};
class DerivedB : public Base
{
public:
virtual void DoA() override;
virtual void DoB() override;
virtual void DoC() override;
};
All of methods DoA(), DoB() ... operate only on members of base class,
and some of them might call base class methods inside of them. At runtime, I create object of type DerivedA as default, but I might need to change it to DerivedB or DerivedC. However I find it useless to create these object by copying state of DerivedA and initializing it again. I think the solution might be to cast DerivedA to any other type, but I'm not sure if it's safe and if it's a good design. Any opinions?
The example you give sounds like you are trying to develop some sort of state machine with the different derived classes being different states. This is normally handled by using the letter/envelope idiom where the envelopes are the different states and the letter contains the common data.
#include <memory>
struct letter
{
float m_x;
float m_y;
};
class base_envelope
{
std::unique_ptr< letter > data_;
base_envelope( const base_envelope & ) = delete;
base_envelope( base_envelope && ) = delete;
public:
base_envelope(): data_() {};
base_envelope( std::unique_ptr< letter > & d ): data_(std::move(d)) {}
virtual void doA() = 0;
virtual void doB() = 0;
void swap( base_envelope & o ) { std::swap( data_, o.data_ ); }
};
class derived1: public base_envelope
{
public:
derived1(): base_envelope() {}
virtual void doA() override { }
virtual void doB() override { }
std::unique_ptr< base_envelope > change_state();
};
class derived2: public base_envelope
{
public:
derived2(): base_envelope() {}
virtual void doA() override {}
virtual void doB() override {}
std::unique_ptr< base_envelope > change_state()
{
std::unique_ptr< base_envelope > r( new derived1 );
swap( *r );
return std::move( r );
}
};
std::unique_ptr< base_envelope > derived1::change_state()
{
std::unique_ptr< base_envelope > r( new derived2 );
swap( *r );
return std::move( r );
}
You should better have a pointer to Base class and create and assign an object of your derived class when you need:
Base * p = NULL;
// some code ...
p = new DerivedA;
p->DoA(); // DoA from DerivedA class
// some code ...
p = new DerivedB;
p->DoA(); // DoA from DerivedB class
Related
I am now looking for a way to override the "Member Variable Type" in C ++ inheritance.
For Example:
class MemberBase
{
protected:
char* data;
public:
void print_data( void ) { printf("%s\n", data); }
};
class MemberDerivedA : public MemberBase
{
protected:
int number;
public:
void print_A_data( void ) { printf( "A: %d\n", number); }
};
class MemberDerivedB : public MemberBase
{
protected:
double real;
public:
void print_B_data( void ) { printf( "B: %lf\n", real); }
};
and
class Base
{
protected:
MemberBase* a;
public:
Base( MemberBase* a ) { this->a = a; }
void use( void ) { a->print_data(); }
};
class DerivedA
{
public:
DerivedA( MemberDerivedA* a ) : Base(a) { this->a = a; }
// I want to use the "a" member variables as "MemberDerivedA" types
void use_A( void ) { a->print_A_data(); }
};
In the above code, I would like to use the MemberDrivedA class's print_A_data function in the DrivedA class through a member variable a, which inherits from the Base class.
(Of course, the object pointed to by a "pointer a" in DerivedA class is actually an object of type MemberDrivedA)
Of course I can do this with pointer type casting.( cast "a" MemberBase* type to MemberDrivedA* type in DrivedA ) However, I want to find more easy way than casting all access of a.
Is there any way to override "member variable type"?
Thanks in advance.
// I want to use the "a" member variables as "MemberDerivedA" types
You choices:
Store a pointer to the MemberDerivedA object in DerivedA in addition to what the base class stores.
Perform a dynamic_cast of the pointer being held by the base class. Use the pointer only if the cast succeeds.
Rethink your code so you don't need either of the above. This, IMO, is the best choice.
There is absolutely positively no way to have covariant variables without cheating the type system.
class Base
{
protected:
virtual MemberBase* a; // imaginary syntax
public:
Base( MemberBase* a ) { this->a = a; }
void use( void ) { a = new MemberDerivedA; } // oops we just broke MemberDerivedB
};
One way to deal with the situation is to use a covariant virtual function instead.
class Base
{
protected:
virtual MemberBase* a() = 0;
public:
Base( ) = default;
// whatever
};
What if you made the print_data function virtual in base class and override it in the derived class?
class MemberBase
{
protected:
char* data;
public:
virtual void print_data( void ) { printf("%s\n", data); }
};
class MemberDerivedA : public MemberBase
{
protected:
int number;
public:
void print_data( void ) { printf( "A: %d\n", number); }
};
class MemberDerivedB : public MemberBase
{
protected:
double real;
public:
void print_data( void ) { printf( "B: %lf\n", real); }
};
Say I have a parent class Parent and child classes Child1 and Child2 having the latter implementing MyInterface:
class Parent {
public:
Parent();
virtual ~Parent();
virtual void MyMethod();
}
class MyInterface {
public:
virtual ~MyInterface() {}
virtual void MyInterfaceMethod() = 0;
}
class Child1 : public Parent {
public:
Child1();
virtual ~Child1();
}
class Child2 : public Parent, MyInterface {
public:
Child2();
virtual ~Child2();
virtual void MyInterfaceMethod() override;
}
And say I'm given a Parent* pointer, and I want to check if the object is implementing MyInterface and if yes, cast it to MyInterface*.
I've tried to achieve it this way:
void MyFunction(Parent* p) {
MyInterface* i = dynamic_cast<MyInterface*>(p);
if (i != 0)
DoSomething();
else
cout << "Cannot do anything.";
}
But i always equals to 0 which says it is never casted to the type MyInterface* even if I know for sure that the object has the good type.
How should I achieve this?
Child2 private inherits from MyInterface, unless MyFunction() has the privilege to access the private base subobject, dynamic_cast will always fail.
Since MyInterface seems to be an interface, I think you want public inheritance.
class Child2 : public Parent, public MyInterface { }
// ~~~~~~
LIVE (Other errors fixed)
Your classes must be polymorphic types for dynamic_cast to work.
The simplest way of achieving this is to add
virtual ~Parent() = default;
in the public area of the Parent class. Then the dynamic_cast will sniff around the inheritance tree for your interface like a truffling pig.
Alternatively, instead of using dynamic_cast, we could use the Visitor Pattern:
#include <iostream>
class MyInterface {
public:
virtual void DoSomething() = 0;
};
class Parent {
public:
virtual ~Parent() = default;
virtual void accept(class Visitor& visitor) = 0;
};
class Child1 : public Parent {
public:
virtual void accept(Visitor& visitor);
};
class Child2 : public Parent, public MyInterface {
public:
virtual void accept(Visitor& visitor);
virtual void DoSomething();
};
class Visitor
{
public:
void visit(Child1& child);
void visit(Child2& child);
};
void Child1::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::accept(Visitor& visitor) { visitor.visit(*this); }
void Child2::DoSomething() { std::cout << "Do something.\n"; }
void Visitor::visit(Child1& child) { std::cout << "Cannot do anything.\n"; }
void Visitor::visit(Child2& child) { child.DoSomething(); }
void MyFunction(Parent& p) {
Visitor v;
p.accept(v);
}
int main()
{
Child1 c1;
Child2 c2;
MyFunction(c1);
MyFunction(c2);
}
Output:
Cannot do anything.
Do something.
I am playing around with the following structure of classes which use std::shared_ptr (C++11):
#include <string>
#include <iostream>
#include <vector>
#include <memory>
//class Member is given by a 3rd party library, CAN'T modify its structure!
class Member {//no instance of this class allowed
public:
Member() {};//should never be called
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor because of child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
virtual void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
virtual
std::shared_ptr< Member >
get_var() {return var;}
virtual void
set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
virtual
std::shared_ptr< ChildMember >
get_var() {return var;} //(2) : try to comment
virtual void
set_var ( std::shared_ptr< ChildMember > v) { var = v;}
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;
cb->var->foo2(); //can access directly as well;
//cb->var = std::make_shared<ChildMember>();
func(cb);
}
What i try to do is design two classes (Base and ChildBase) where each one has its own member Member / ChildMember. After full usage of ChildBase object and its member object of type ChildMember, i pass it to a function func which receives Base and should, using polymorphism call the proper foo of a member var.
Problems:
(1)
In the variant in the above, compiler complains that:
overriding 'virtual std::shared_ptr<Member> Base::get_var()'
get_var() {return var;}`
(2)
If i comment-out ChildBase implementation of get_var, this function is treated as Base and thus returns a pointer to Member which does not have foo2.
(3)
I can also comment out cb->get_var()->foo2() . The whole things compiles, but it seems it does not call ChildMember::foo() as there is no output Child Member;
Something is (hopefully) slightly messed up but i don't see what. Could you guys please help to correct it?
EDIT1:
based on Abhijit Kadam answer, the following code fully compiles:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
std::shared_ptr< Member >
get_var() {return var;}
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
void func_vec( std::vector<
std::shared_ptr<Base>
> vec) {
for (unsigned int i=0;i<vec.size();i++)
vec[i]->get_var()->foo();
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
func(cb);
std::vector< std::shared_ptr<Base>> vec;
vec.push_back(cb);
func_vec(vec);
cb->var->foo2();
/*std::shared_ptr<ChildMember> ptr(std::dynamic_pointer_cast<ChildMember>(cb->get_var()) );
if (ptr) {
ptr->foo2();
} */
}
EDIT2
added an answer below.
As the return types of overriding functions cannot differ I would have use dynamic cast to implement the solution. Hence no need to have virtual functions for `get_var and set_var'. Also no need for foo2 to be virtual unless the class would be further derived by some other class.
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
shared_ptr<ChildMember> ptr(dynamic_pointer_cast<ChildMember>(cb->get_var()) );
if (ptr) {
ptr->foo2();
}
}
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
std::shared_ptr< Member >
get_var() {return var;}
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
std::shared_ptr< ChildMember > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
virtual
std::shared_ptr< Member >
get_var() {return var;}
virtual
std::shared_ptr< ChildMember >
get_var() {return var;} //(2) : try to comment
It's wrong overriding.
n3337 10.3/7
The return type of an overriding function shall be either identical to the return type of the overridden
function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the
return types of the functions are covariant if they satisfy the following criteria:
— both are pointers to classes, both are lvalue references to classes, or both are rvalue references to
classes
— the class in the return type of B::f is the same class as the class in the return type of D::f, or is an
unambiguous and accessible direct or indirect base class of the class in the return type of D::f
— both pointers or references have the same cv-qualification and the class type in the return type of D::f
has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.
All conditions fails in your case. You can use raw-pointers, or references for this, something like http://liveworkspace.org/code/4eQWBI$1
But I think you should rewrite your interface and not use foo2, if it's not virtual.
To solve your problem, see this modified and annotated version of your code:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember : public Member {
public:
ChildMember() {};
virtual void foo() {
std::cout<<"Child Member"<<std::endl;
}
virtual void foo2() {
std::cout<<"unique foo in child"<<std::endl;
}
};
class Base {
public:
Base() {};
// maybe you should have a virtual dtor here
virtual ~Base();
// note: NOT virtual
std::shared_ptr< Member >
get_var() {return var;}
// also NOT virtual
void set_var ( std::shared_ptr< Member > v) { var = v;}
std::shared_ptr< Member > var;
};
class ChildBase : public Base {
public:
ChildBase() {
//var = std::make_shared<ChildMember>();
};
// non-virtual version which casts var to the correct type
std::shared_ptr< ChildMember >
get_var() {return std::dynamic_pointer_cast<ChildMember>(var);}
// note: no var here, use the one from Base
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase> cb( std::make_shared<ChildBase>());
cb->set_var (std::make_shared<ChildMember>() );
cb->get_var()->foo2();//(3) want to use unique functions of ChildBase;
// This can't work:
//cb->var->foo2(); //can access directly as well;
//cb->var = std::make_shared<ChildMember>();
func(cb);
}
shared_ptr is not a pointer, so covariance doesn't apply.
Typically, I'm sceptical about the use of covariance anyway. I
generally find it cleaner for the derived class to not change
the return types, and to provide a new function if it needs to
return a pointer to a derived function. In your case, I'd say
that this is essential, since you actually have two pointers
(which could end up pointing to different objects).
after a while, i though the following code might be a good solution:
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Member {//no instance of this class allowed
public:
Member() {};
virtual ~Member() = 0;//pure virtual distructor;
virtual void foo() {
std::cout<<"Member"<<std::endl;
}
};
Member::~Member() {} //need to define destructor for child classes
class ChildMember1 : public Member {
public:
ChildMember1() {};
virtual void foo() {
std::cout<<"Child Member 1"<<std::endl;
}
void foo1() {
std::cout<<"unique foo in child 1"<<std::endl;
}
};
class ChildMember2 : public Member {
public:
ChildMember2() {};
virtual void foo() {
std::cout<<"Child Member 2"<<std::endl;
}
};
class ChildChildMember2 : public ChildMember2 {
public:
ChildChildMember2() {};
virtual void foo() {
std::cout<<"Child-Child Member 2"<<std::endl;
}
};
class Base {
public:
Base() {};
virtual
~Base() {};
virtual
std::shared_ptr< Member >
get_var() = 0; //purely abstract class
};
class ChildBase1 : public Base {
public:
ChildBase1() {
var = std::make_shared<ChildMember1>();
};
virtual
std::shared_ptr< Member >
get_var() {return var;}
std::shared_ptr< ChildMember1 > var;
};
class ChildChildBase : public ChildBase1 {
public:
ChildChildBase() {
var2 = std::make_shared< ChildChildMember2>();
}
virtual
std::shared_ptr< Member >
get_var() { return var2; }
std::shared_ptr< ChildChildMember2 > var2;
};
class ChildBase2 : public Base {
public:
ChildBase2() {
var = std::make_shared<ChildMember2>();
};
virtual
std::shared_ptr< Member >
get_var() {return var;}
std::shared_ptr< ChildMember2 > var;
};
void func(std::shared_ptr<Base> b) {
b->get_var()->foo();// process input using polymorphism
}
int main()
{
std::shared_ptr<ChildBase1> cb1( std::make_shared<ChildBase1>());
cb1->var->foo1();
func(cb1);
std::shared_ptr<ChildBase2> cb2( std::make_shared<ChildBase2>());
func(cb2);
std::shared_ptr<ChildChildBase> ccb( std::make_shared<ChildChildBase>());
func(ccb);
}
I think it achieves what i was after without parallel inheritance or dynamic casting. It also has more than 1 lvl of inheritance.
The output is:
unique foo in child 1
Child Member 1
Child Member 2
Child-Child Member 2
Consider the following hierarchy:
class Base
{
virtual void Method() = 0;
virtual void Accept(Visitor *iVisitor) = 0;
};
class Derived1: public Base
{
virtual void Method(){//impl}
virtual void Accept(Visitor *iVisitor)
{
iVisitor->Visit(this);
}
};
class Derived2: public Base
{
virtual void Method(){//impl}
virtual void Accept(Visitor *iVisitor)
{
iVisitor->Visit(this);
}
};
and the visitor class:
class VisitorInterface
{
virtual void Visit(Derived1 * param);
virtual void Visit(Derived2 * param);
}
class Visitor: public VisitorInterface
{
void Visit(Derived1 * param){}
void Visit(Derived2 * param){}
}
Usually I use the visitor pattern to achieve double dispatching when the overload method depends on the parameter type, but I have only the pointer to the base class.
For example:
void foo(Visitor *visitorPtr, Base * basePtr)
{
basePtr->Accept(visitorPtr);
}
I think this is the only way to achieve double dispatching since the dynamic binding of virtual functions should happen only on the object upon which the method is called and not on its parameters (derived types).
Now I encountered a new situation, where I need a sort of Visit method overloading on multiple parameters. Something like this:
class VisitorInterfaceMultiple
{
virtual void Visit(Derived1 * param1, Derived2 * param2);
virtual void Visit(Derived2 * param1, Derived3 *param2);
}
I cannot use the classical visitor pattern solution because accept method is called on only one of the parameters.
My question is: does exist any similar visitor pattern solution, or something similar, that I could use in this situation? (I need to overload Visit with exact 2 parameters, no more than 2).
I created for you "triple" dispatch pattern: http://ideone.com/FoXNW
It is quite easy.
Main part below:
class Derived1;
class Derived2;
class Visitor;
class Base
{
public:
virtual void Accept(Visitor &iVisitor, Base& param1) = 0;
virtual void Accept(Visitor &iVisitor, Derived1& param2) = 0;
virtual void Accept(Visitor &iVisitor, Derived2& param2) = 0;
};
class Visitor
{
public:
virtual void Visit(Derived1 & param1, Derived1 ¶m2) { cout << "11\n"; }
virtual void Visit(Derived1 & param1, Derived2 ¶m2) { cout << "12\n"; }
virtual void Visit(Derived2 & param1, Derived1 ¶m2) { cout << "21\n"; }
virtual void Visit(Derived2 & param1, Derived2 ¶m2) { cout << "22\n"; }
};
class Derived1: public Base
{
public:
virtual void Accept(Visitor &iVisitor, Base& param1)
{ param1.Accept(iVisitor, *this); }
virtual void Accept(Visitor &iVisitor, Derived1& param2)
{ iVisitor.Visit(*this, param2); }
virtual void Accept(Visitor &iVisitor, Derived2& param2)
{ iVisitor.Visit(*this, param2); }
};
class Derived2: public Base
{
public:
virtual void Accept(Visitor &iVisitor, Base& param1)
{ param1.Accept(iVisitor, *this); }
virtual void Accept(Visitor &iVisitor, Derived1& param2)
{ iVisitor.Visit(*this, param2); }
virtual void Accept(Visitor &iVisitor, Derived2& param2)
{ iVisitor.Visit(*this, param2); }
};
void Visit(Visitor& visitor, Base& param1, Base& param2)
{
param2.Accept(visitor, param1);
}
Note that implementation of Derived1 and Derived2 is literally identical. You can enclose this in macro if you have more derived.
Can I change this code to make it work? Is it possible to combine template method pattern and multiple inheritance? It seems to be very convenient to implement different algorithms in different classes. Thank you.
class TBase {
public:
virtual void Do1() const = 0;
virtual void Do2() const = 0;
void Do() const {
Do1();
Do2();
}
};
class TFirstAlgorithm {
public:
void Do1() const {}
};
class TSecondAlgorithm {
public:
void Do2() const {}
};
class TAlgorithm
: public TBase
, public TFirstAlgorithm
, public TSecondAlgorithm
{};
Fundamentally, your problem is that TFirstAlgorith::Do1 isn't related to TBase::Do1 (and likewise TSecondAlgorithm::Do2 to TBase::Do2.
One possible way to fix that would be to make them related:
class TBase {
public:
virtual void Do1() const = 0;
virtual void Do2() const = 0;
void Do() const {
Do1();
Do2();
}
};
class TFirstAlgorithm : public virtual TBase {
public:
void Do1() const { }
};
class TSecondAlgorithm : public virtual TBase {
public:
void Do2() const { }
};
class TAlgorithm
: public TFirstAlgorithm
, public TSecondAlgorithm
{};
You can use implementations for Do1 and Do2 and call appropriate algorithm inside them.
class TBase {
public:
virtual void Do1() const = 0;
virtual void Do2() const = 0;
void Do() const {
Do1();
Do2();
}
};
class TFirstAlgorithm {
public:
void Do1() const {}
};
class TSecondAlgorithm {
public:
void Do2() const {}
};
class TAlgorithm
: public TBase
, public TFirstAlgorithm
, public TSecondAlgorithm
{
virtual void Do1() const { TFirstAlgorithm::Do1() ; }
virtual void Do2() const { TSecondAlgorithm::Do2() ; }
};