class Base{
protected:
int remainItems = 0;
public:
Base(){}
virtual int numOfItem() = 0;
};
class Deveried1 : public Base{
public:
Deveried1() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 5;
}
};
class Deveried2 : public Base{
public:
Deveried2() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 10;
}
};
class Deveried3 : public Base{
public:
Deveried3() :Base(){ remainItems = numOfItem(); }
int numOfItem(){
return 10;
}
};
int main(){
Base* foo = new Deveried3;
}
With this design, for every deveried class, I must do the same thing in constructor to initalize remainItems. I'd like to know if there are some better way/pattern in this situation.
Indeed, you can't call derived class functions from the base class constructor, so this kind of twisted inversion of dependencies can't work. I'd pass the value to the base-class constructor:
Base(int numOfItems) : remainItems(nomOfItems) {}
Derived1() : Base(5) {}
Derived2() : Base(10) {}
I do not see any benefit in the method, so I removed it and added an option to pass the variable in the base class constructor:
class Base{
protected:
int remainItems;
public:
Base(remainItems = 0) { this->remainItems = remainItems; }
};
class Deveried1 : public Base{
public:
Deveried1() :Base(5){}
}
};
class Deveried2 : public Base{
public:
Deveried2() :Base(10){}
}
};
class Deveried3 : public Base{
public:
Deveried3() :Base(10){}
}
};
int main(){
Base* foo = new Deveried3;
}
I believe what you're looking for is called the Non-Virtual Interface pattern.
How to implement an interface class using the non-virtual interface idiom in C++?
Related
I'm currently trying to wrap my head around the basics of C++ inheritance. Consider the following piece of code:
// Interfaces
class InterfaceBase
{
public:
virtual void SomeMethod() = 0;
};
class InterfaceInherited : public InterfaceBase
{
};
// Classes
class ClassBase : public InterfaceBase
{
public:
virtual void SomeMethod()
{
}
};
class ClassInherited : public ClassBase, public InterfaceInherited
{
};
int main()
{
ClassBase myBase; // OK
ClassInherited myInherited; // Error on this line
return 0;
}
Here I have two interfaces with an inheritance relationship. The same goes for the two classes which implement the interfaces.
This gives me the following compiler error:
C2259 'ClassInherited': cannot instantiate abstract class
It seems that the class ClassInherited does not inherit the implementation of SomeMethod from ClassBase. Thus it is abstract and cannot be instantiated.
How would I need to modify this simple example in order to let ClassInherited inherit all the implemented methods from ClassBase?
You are encountering a diamond problem.
The solution is to use virtual inheritance (Live), to ensure that only one copy of base class members are inherited by grand-childs:
// Interfaces
class InterfaceBase
{
public:
virtual void SomeMethod() = 0;
};
class InterfaceInherited : virtual public InterfaceBase
{
};
// Classes
class ClassBase : virtual public InterfaceBase
{
public:
virtual void SomeMethod()
{
}
};
class ClassInherited : public ClassBase, public InterfaceInherited
{
};
int main()
{
ClassBase myBase; // OK
ClassInherited myInherited; // OK
return 0;
}
I'm getting a compile error when I try to compile my code.
The error is this:
multi.cc: In function ‘int main()’:
multi.cc:35: error: cannot declare variable ‘mdc’ to be of abstract type ‘MostDerivedClass’
multi.cc:27: note: because the following virtual functions are pure within ‘MostDerivedClass’:
multi.cc:13: note: virtual int Interface2::common_func()
multi.cc:36: error: request for member ‘common_func’ is ambiguous
multi.cc:13: error: candidates are: virtual int Interface2::common_func()
multi.cc:21: error: virtual int InterimClass::common_func()
And here is my code:
class Interface1 {
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class Interface2 {
public:
virtual int common_func() = 0;
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass, public Interface2 {
public:
virtual int new_func() {
return 20;
}
};
int main() {
MostDerivedClass mdc;
int x = mdc.common_func();
cout << "The value = " << x << endl;
Interface2 &subset_of_funcs = dynamic_cast<Interface2 &>(mdc);
x = subset_of_funcs.common_func();
}
My questions:
How do I tell the compiler that common_func() is already implemented by the InterimClass which is a base class of MostDerivedClass?
Is there another way to fix my problem? What I would really like to do is to be able to also call common_func from Interface2. I'm working with some legacy code with a huge amount of methods in Interface1. In my new code, I only want to call a small set of these Interface1 functions, plus a few that I need to add.
You need to define a common_func() anyway in MostDerivedClass to satisfy your inheritance from Interface2
you can try something like
virtual int common_func() {
return InterimClass::common_func();
}
This is most useful if you cannot change the first Interface1
If you want a real inheritance relationship between your classes you need to follow Lol4t0 advice. Extract a superclass from Interface1, and make Interface2 subclass of this newly created class. Example :
class RootInterface{
public :
virtual int common_func() = 0;
virtual ~RootInterface(){}
};
class Interface1 : public virtual RootInterface{
public:
virtual ~Interface1() {};
};
class Interface2 : public virtual RootInterface{
public:
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass, public Interface2 {
public:
virtual int new_func() {
return 20;
}
};
Add an override in MostDerivedClass, and from it call InterimClass::common_func().
First of all, I don't really understand the sense of your code.
You need to know that only Interface1::common_func is implemented.
Why don't you make Interface2 inherit from Interface1? I guess you want for both common_func methods to be equal.
Example code (uses polymorphism):
class Interface1
{
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class Interface2 : public Interface1 {
public:
virtual int common_func() = 0;
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class InterimClass : public Interface2 {
public:
virtual int common_func() {
return 10;
}
};
class MostDerivedClass : public InterimClass {
public:
virtual int new_func() {
return 20;
}
};
int test_func()
{
Interface1 * i1 = new MostDerivedClass;
int x = i1->common_func();
cout << "The value = " << x << endl;
Interface2 * i2 = new MostDerivedClass;
x = i2->common_func();
return 0;
}
Let the second interface be derived from the first interface, remove the declaration of virtual int common_func() = 0; from the second interface, & use the keyword virtual to guide the compiler to the implementation.
class Interface1 {
public:
virtual int common_func() = 0;
virtual ~Interface1() {};
};
class BaseClass : public virtual Interface1 {
public:
virtual int common_func() {
return 10;
}
};
class Interface2 : public virtual Interface1{
public:
virtual int new_func() = 0;
virtual ~Interface2() {};
};
class DerivedClass : public virtual BaseClass, public virtual Interface2 {
public:
virtual int new_func() {
return 20;
}
};
My problem is the following:
int main()
{
Base* derivedobject = new Derived1();
derivedobject->GetProperties()-> ???
return 0;
}
//********************
// BaseClass.h
//********************
struct PropertyStruct
{
int x;
};
class Base
{
public:
Base();
~Base();
virtual PropertyStruct GetProperties() = 0;
private:
};
//********************
// DerivedClass1.h
//********************
struct PropertyStruct
{
int y;
};
class Derived1 : public Base
{
public:
Derived1();
~Derived1();
PropertyStruct GetProperties() { return myOwnDifferentProperties; };
private:
};
//********************
// DerivedClass2.h
//********************
struct PropertyStruct
{
float z;
};
class Derived2 : public Base
{
public:
Derived2();
~Derived2();
PropertyStruct GetProperties() { return myOwnDifferentProperties };
private:
};
If I do it like that I'm going to get an error saying that PropertyStruct is a redefinition. If I use a namespace or rename the struct inside the derived class I am then going to get an error telling me that the return type is not the same as defined by Base.
If I define the virtual functions return type as a pointer it compiles, though the next problem when accessing the function "GetProperties" from the main method (in this example) the base object does not know what variables are inside the struct of the derived class.
Is there any way I can realize this ?
That I can get the different properties of each derived object but using the base class object ?
As others have mentioned, there are ways to achieve your goals here but ultimately you will find yourself writing code like the following:
Base * object = ...;
if object is Derived1 then
get Property1 and do something with it
else if object is Derived2 then
get Property2 and do something with it
This is an anti-pattern in object-oriented programming. You already have a class hierarchy to represent the differences between the various derived types. Rather than extracting the data from your objects and processing it externally, consider adding a virtual function to the base class and letting the derived classes do the processing.
class Base
{
public:
virtual void DoSomething() = 0;
};
class Derived1 : Base
{
public:
void DoSomething()
{
// use myOwnDifferentProperties as necessary
}
private:
PropertyStruct myOwnDifferentProperties;
};
If it's not appropriate to put the required processing in the derived classes (i.e. if it would introduce unwanted responsibilities) then you may want to consider the Visitor Pattern as a way to extend the functionality of your hierarchy.
Since template functions cannot be virtual you can use hierarchy of your properties. It's only one way, no other ways. For get elements of derived Properties you should use virtual getter functions.
struct BaseProp
{
virtual ~BaseProp() { }
virtual boost::any getProperty() const = 0;
};
struct PropertyStruct : BaseProp
{
boost::any getProperty() const { return x; }
private:
int x;
};
struct PropertyStruct2 : BaseProp
{
boost::any getProperty() const { return y; }
private:
float y;
};
class Base
{
public:
virtual std::shared_ptr<BaseProp> GetProperties() const = 0;
virtual ~Base() { }
}
class Derived
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct(); }
};
class Derived2
{
public:
std::shared_ptr<BaseProp> GetProperties() const { return new PropertyStruct2(); }
};
You can use template class to do that:
struct PropertyStruct1 {
float f;
};
struct PropertyStruct2 {
int i;
};
template<class T>
class A{
public:
T GetProperties() {return mProps;}
private:
T mProps;
};
int main (int argc, const char * argv[]) {
A<PropertyStruct1> a1;
int f = a1.GetProperties().f;
A<PropertyStruct2> a2;
int i = a2.GetProperties().i;
return 0;
}
I have a logic in base class constructor. The result of the logic has to be captured in the derived class constructor in a temporary variable. Is there a way to do it?
For example
class Base
{
Base() { int temp_value = some_logic; }
};
class Derived : public Base
{
Derived() { // need the temp value here.. }
};
Thanks,
Gokul.
I guess the easiest way I can think of would be to just separate some_logic into it's own method...
class Base
{
Base() { int temp_value = initializationLogic(); }
int initializationLogic(){ return some-logic;}
};
class Derived : public Base
{
Derived() { int temp_value_here_too = initializationLogic(); }
};
Either:
class Base
{
protected int not_so_temp_value;
Base() { not_so_temp_value = some_logic_result; }
};
class Derived : public Base
{
Derived() { // read the not_so_temp_value member here.. }
};
Or:
class Base
{
Base(int some_logic_result) { int temp_value = some_logic; }
};
class Derived : public Base
{
static Derived* create()
{
int some_logic_result = some_logic;
return new Derived(some_logic_result);
}
Derived(int some_logic_result) : Base(some_logic_result)
{ // use the some_logic_result here.. }
};
This is the one i am planning to use
class Base
{
Base(int& some_logic_result) { some_logic_result = some_logic; }
};
class Derived : public Base
{
Derived(int some_logic_result = 0) : Base(some_logic_result)
{ // use the some_logic_result here.. }
};
Thanks,
Gokul.
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.