Nested classes, inheritance and shared pointers in C++ - c++

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.

Related

C++ Polymorphic Data Structure

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.

Can I declare a different typedef depending on class?

Is it possible to have a different type definition based on which derived class is instantiated?
Say I have a parent class with a virtual function func(), two int members and a vector of type myType, and two child classes, which share the same int members, and the vector, but their implementation of func() require myType to be slightly different.
For example:
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<myType> vec;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
Can I do something like this? when I have tried it, it creates a circular dependency in the header files, because class Parent is required to be included first, but then it requires myType to be defined.
Is there a way of forward declaring myType depending on class? or do I just need to include a different vector of myType in each class like so:
class Parent {
protected:
int myMember;
int myOtherMember;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
std::vector<myType> vec;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
std::vector<myType> vec;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
This is a job for templateman!
First we declare Parent
template <class TYPE>
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<TYPE> vec;
public:
Parent(TYPE variable);
virtual int func() = 0;
};
Unfortunately a custom type contained within Child1 is out with this approach because the type needs to be declared before we can specialize a template on it. I'm using int and double here for ease. Replace as needed.
using Child1Type = int;
// or typedef int Child1Type; pre-C++11
class Child1 : public Parent<Child1Type> {
public:
Child1(Child1Type variable) : Parent(variable){};
int func() {return someFunc();};
};
using Child2Type = double;
class Child2 : public Parent<Child2Type> {
public:
Child2(Child2Type variable) : Parent(variable){};
int func() {return someOtherFunc();};
};
EDIT
Kicking myself for not getting this earlier (and burning way too much time because I knew it had to be possible, but was thinking in the wrong direction)
Declare the type up in Parent. Set the access based on who need to be able to see the type. Here I made Type public to test it out in main. The Type is declared in Parent and is visible to (and through because it's public) the Children.
Also stripped out everything that wasn't immediately necessary and used fixed width integer types so I could easily demonstrate the differences.
I think this is exactly what Pixelchemist was alluding to.
template <class TYPE>
class Parent {
public:
using Type = TYPE; // declare Type here
protected:
int myMember;
int myOtherMember;
std::vector<Type> vec; // visible here
public:
Parent(Type variable); // here
virtual ~Parent(){}
virtual int func() = 0;
};
class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced
// only once, here in the specialization
public:
Child1(Type variable) : Parent(variable){};
};
class Child2 : public Parent<uint32_t> {
public:
Child2(Type variable) : Parent(variable){};
};
int main()
{
// and visible way down here in main through Child1 and Child2
std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl;
std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl;
}
output is
Child 1: 2
Child 2: 4
You could simply use templates:
template<class T>
struct Base
{
std::vector<T> v;
};
struct D1 : public Base<int>
{
// all stuff in here comes into play when deriving from Base is already done
// Thus, compiler cannot know any typedefs from here inside Base...
};
struct D2 : public Base<double>
{
};
where you cannot use a typedef from derived in base class. See CRTP refer to typedef in derived class from base class.
This is what templates are for:
<template typename T>
class Child : public Parent {
private:
std::vector<T> vec;
public:
Child(variable) : Parent(variable) {};
int func() { return someOtherFunc(); };
}
Then Child is declared as something like:
Child<int> myChildInstance(10);

Exposing base class enum without tediously listing enumerators

In C++11, I can expose an enumerator which is protected in a base class, to users of a derived class, as follows:
class Base
{
protected:
enum Waldo { hidden, found };
};
class Derived : public Base
{
public:
using Base::Waldo;
}
void foo()
{
Derived::Waldo w = Derived::Waldo::found;
}
Unfortunately, in C++03, Derived::Waldo::found is illegal, and Derived::found is met with 'Base::Waldo Base::found' is protected within this context.
I could work around that by also writing a using for each enumerator:
class Derived : public Base
{
public:
using Base::Waldo;
using Base::hidden;
using Base::found;
}
void foo()
{
Derived::Waldo w = Derived::found; // works in C++03
}
but this can be really tedious to do if the enumerator has many enumerators. Is there a way to pull off this enum-exposing in C++03 without this tedium?
SCNR!
struct Wrap
{
enum Waldo { hidden, found };
};
class Base : protected Wrap
{
};
class Derived : public Base
{
public:
using Base::Wrap;
};
void foo()
{
Derived::Wrap::Waldo w = Derived::Wrap::found;
}
Edit: Or you put it inside:
class Base
{
protected:
struct Wrap
{
enum Waldo { hidden, found };
};
};
class Derived : public Base
{
public:
using Base::Wrap;
};
void foo()
{
Derived::Wrap::Waldo w = Derived::Wrap::found;
}
Well, I think there are lots of different ways to do this, depending on what you want to do with the enum. Here is one:
struct WaldoStates
{
enum States{hidden, found};
};
class Base
{
public:
typedef WaldoStates Waldo;
};
class Derived : public Base
{
};
void foo()
{
WaldoStates::States state = Derived::Waldo::found;
}
Now, this is good if simply want the states to be accessible with something like myClass::Waldo::hidden in any class of the inheritance tree. If you want to be able to set different states for some of the derived classes, you may want to do something like this instead:
struct WaldoStates
{
typedef int State;
};
struct DefaultWaldoStates : public WaldoStates
{
enum States{hidden, found};
};
struct OtherWaldoStates : public WaldoStates
{
enum States{stillHidden, alreadyFound};
};
class Base
{
public:
typedef DefaultWaldoStates Waldo;
};
class Derived : public Base
{
};
class OtherDerived : public Base
{
public:
typedef OtherWaldoStates Waldo;
};
void foo()
{
WaldoStates::State state0 = Derived::Waldo::found;
WaldoStates::State state1 = OtherDerived::Waldo::alreadyFound;
}

Problematic design modifiying/accessing information of a derived class using the base object

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 want to change the parent's member data to an instance of another class

In C++, I have a class A, and a class B.
In class A, there is a object (of class B) , I want to change the class A member data in the object of class B. How can I do that ?
I want to do this:
class A {
public:
A() {
new B(this);
}
private:
int i;
};
class B {
public:
B(A* parent) {
this->parent = parent;
}
change() {
parent->i = 5;
}
private:
A* parent;
};
In declaration of class A you need to define class B as a friend:
friend class B;
Rather than setting B as a friend class to A, a better method to preserve encapsulation would be to add a setter method to class A.
Your class A would then look somewhat like this:
class A {
public:
A() {
new B(this);
}
void set_i(int value)
{
i = value;
}
private:
int i;
};
Then in your class B implementation, call set_i().
class B {
public:
B(A* parent) {
this->parent = parent;
}
change() {
parent->set_i(5);
}
private:
A* parent;
};
This way you're not exposing and relying on private implementation details of class A in class B.
class A {
friend class B;
private:
int i;
public:
A() : i(0) {
new B(this);
}
};