After some searching I've yet to find an existing question which address this issue. My apologies if I missed something.
I have a base class with a params structure and setter. I would like to redefine what that params structure looks like in a derived class and set it via a base class pointer. Something like the following for example.
class A
{
public:
struct paramsType
{
int a;
int b;
};
protected:
paramsType params;
public:
void setParams(const paramsType& params) { this->params = params; }
};
class B : public A
{
public:
struct paramsType
{
int c;
int d;
int e;
};
};
class C : public A
{
public:
struct paramsType
{
int f;
};
};
int main () {
A* ptrB = new B();
A* ptrC = new C();
B::paramsType paramsB;
paramsB.c = 0;
paramsB.d = 1;
paramsB.e = 2;
C::paramsType paramsC;
paramsC.f = 3;
ptrB->setParams(paramsB);
ptrC->setParams(paramsC);
delete ptrB;
delete ptrC;
}
I've tried making the base class "setParams" virtual and redefining it in the derived class, however when I call the method via the base class pointer, it has incompatible types.
In the real use case B and C share a ton of functionality which is implemented in A. They just have different parameter sets. I only have access to a base class pointer, but will know if the object is a B or a C. Is there an elegant way to address this?
Thanks!
You can't redefine a type but what you can do is a have a common base class for the parameters.
So you could make A::paramsType a base class and derive B::paramsType and C::paramsType from that. Then store a pointer to A::paramsType in class A. That way you can use a common base class for passing in the parameters.
However, in order to access members of B::paramsType and C::paramsType you'll need to cast down the inheritance hierarchy. You could implement that in a member function. If B::paramsType is derived from A::paramsType, it will be able to access all public and protected members of A::paramsType; likewise for C::paramsType.
It will be like this:
class A
{
public:
struct paramsType
{
virtual ~paramsType() = default;
int a;
int b;
};
protected:
std::unique_ptr<paramsType> params;
public:
void setParams(std::unique_ptr<paramsType> params) { this->params = std::move(params); }
};
class B : public A
{
public:
struct paramsType : A::paramsType
{
int c;
int d;
int e;
};
private:
B::paramsType* getParams() { return dynamic_cast<B::paramsType*>(params.get()); }
};
A working version here.
In your example, just change A to
class A
{
public:
struct paramsType
{
int a;
int b;
int c;
};
protected:
paramsType params;
public:
void setParams(const paramsType& params) { this->params = params; }
};
Then A can use paramsType::a and b while C can just ignore paramsType::b and c.
Related
class Builder
{
public:
virtual void Build(int a) = 0;
};
class ConcreteBuilder1 : public Builder
{
public:
void Build(int a);
};
class ConcreteBuilder2 : public Builder
{
public:
void Build(int a. struct A* a);
};
So My question is how to design Build() method to take both parameters(int, struct* A). But with same builder interface ?
So that,
int x;
struct A* y;
Builder concrteBuilder1 = new ConcreteBuilder1();
concrteBuilder1 ->Build() // // Here I am forced to pass struct A* a eventhough not needed for concerte builder1 . And I am also forced to forced to change Builder interface too.
My apologies if I did not convey the question clearly.
Builder usually builds an object of another class. You may try something similar to this:
class ToBuild
{
//some code here
};
class Builder
{
public:
virtual ToBuild * build() = 0;
};
class ConcreteBuilder : public Builder
{
int _valA;
int _valB;
public:
ToBuild * build() override
{
ToBuild * obj = new ToBuild();
//initalize obj using _valA and _valB variables;
return obj;
}
ConcreteBuilder& valA(const int val)
{
_valA = val;
return *this;
}
ConcreteBuilder& valB(const int val)
{
_valB = val;
return *this;
}
};
int main()
{
ConcreteBuilder b;
ToBuild * obj = b.valA(1).valB(2).build();
//some code
delete obj;
return 0;
}
[edit]
You can write another derived class with as many parameters as you want and still use a single 'build' method.
Add
using Builder::Build;
to the derived class's declarations. This will import this symbol into the derived class, and make both it, and the derived class methods, of the same name, available to overload resolution. I.e.
using Builder::Build;
void Build(int a);
I'm ignoring the fact that you can't construct the derived class anyway, since it fails to implement this pure virtual function from the base class.
Derived class override their functions from the one which has same parameters and same return value.
So if you declare a function like...
class Builder
{
public:
virtual void Build() = 0;
};
class ConcreteBuilder1 : public Builder
{
public:
void Build(int a);
};
class ConcreteBuilder2 : public Builder
{
public:
void Build(int a. struct A* a);
};
Here, Build function in ConcreteBuilder1 class treated as a new function, not override function.
So try this.
class Builder
{
public:
virtual void Build(int a, A* b = 0) = 0;
};
class ConcreteBuilder1 : public Builder
{
public:
void Build(int a);
};
class ConcreteBuilder2 : public Builder
{
public:
void Build(int a, struct A* a);
};
I wish it's helpful for you.
The program below fails, obviously, in the return expression:
#include <memory>
class Base {
public:
class Nested {
public:
int c;
};
};
class A : public Base {
public:
class Nested : public Base::Nested {
public:
int c = 1;
};
};
class B : public Base {
public:
class Nested : public Base::Nested {
public:
int c = 2;
};
};
int main() {
std::shared_ptr<Base> X = std::make_shared<A>();
return X::Nested.c;
};
How can I get Nested.c value of X?
In other words, I have one base class (Base) and two derived classes (A and B). Each derived class has a nested class (Nested). I want to called Nested.c from an instance X, which is dynamically selected as one of the derived classes.
Probably just a misconception about nested classes. A Nested class does not magically add members to it's parent class. You need to do that manually, for example:
class Base {
public:
class Nested {
public:
int c;
};
Nested nested; // member of nested class Base::Nested.
};
Keep in mind that Base::Nested, A::Nested and B::Nested are all different classes. Allthough they look similiar they are not related at all.
Maybe the following is what you want:
#include <memory>
class Base {
private:
class Nested {
public:
int c;
};
Nested nested; // member of nested class Base::Nested.
public:
virtual int getC() const { return this->nested.c; }
};
class A : public Base {
private:
class Nested {
public:
int c = 1;
};
Nested nested; // member of nested class A::Nested.
public:
int getC() const override { return this->nested.c; }
};
class B : public Base {
private:
class Nested {
public:
int c = 2;
};
Nested nested; // member of nested class B::Nested.
public:
int getC() const override { return this->nested.c; }
};
int main() {
std::shared_ptr<Base> X = std::make_shared<B>();
return (*X).getC();
};
Each class has it's own member of it's own nested class and returns c with a virtual getter.
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
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 class as follows:
Class A
{
virtual int doSomethingCool() = 0;
};
Class B : public A
{
int doSomethingCool();
};
Now the problem likes , I have a set of classes whcih are dependent on A as interface. I need to change the prototype of the function for one of the derived classes. i.e. i need to pass it a parameter.
Class C: public A
{
int doSomethingCool(int param);
};
Any suggestions how i can achieve this ?
No, you don't need to add it to the base class.
class A
{
public:
virtual int doSomethingCool() = 0 {}
};
class B : public A
{
public:
int doSomethingCool() {return 0;}
};
class C: public A
{
private:
int doSomethingCool(); // hide base class version!
public:
int doSomethingCool(int param) {return param;}
};
You can still call doSomethingCool() if done through a base class pointer:
C c;
//c.doSomethingCool (); // doesn't work, can't access private member
c.doSomethingCool (42);
A &a = c;
a.doSomethingCool ();
//a.doSomethingCool (42); // doesn't work, no member of A has that signature
Add it to the interface and default it to call the existing method. You don't have to do the default but don't make it pure otherwise all derived classes will have to implement. It might be better to leave it undefined or to throw. Depends on what you want to achieve.
class A
{
public:
virtual int doSomethingCool() = 0;
virtual int doSomethingCool(int param) {doSomethingCool()};
};
Make the function doSomethingCool() take the int parameter in A.
class A
{
public:
virtual void doSomethingCool(int param) = 0;
};
There's no problem. You can do it. The only caveat is that it will not be treated as an override of the base class virtual function.
class A
{
public:
virtual void doSomethingCool() = 0;
};
class B : public A
{
public:
void doSomethingCool();
};
class C: Public A
{
public:
void doSomethingCool(int param);
};
int main(){}
So while technically possible, you may really want to relook at the design of your interface class A.
One option may be to provide a default argument to A::doSomethingCool
virtual void doSomethingCool(int = 0) = 0;
This isn't syntactically correct C++.
No you can't change a prototype. How would it be used? What would be the value of the param if the non-parametric version would be called?
I would have introduced another, more specific, interface:
struct A
{
virtual int doSomethingCool() = 0;
};
struct A_specific : A
{
virtual int doSomethingCoolWithThis(int i) = 0;
};
class ConcreteA : public A
{
int doSomethingCool() { return 0; }
};
class ConcreteA_specific : public A_specific
{
int doSomethingCool() { return 0; }
int doSomethingCoolWithThis(int param) { return param; }
};
Then I would program to the correct interface:
int main()
{
const A& a1 = ConcreteA();
const A_specific& a2 = ConcreteA_specific();
a1.doSomethingCool();
a2.doSomethingCool();
a2.doSomethingCoolWithThis(2);
}
Just to give you another idea ;-)
Good luck!