I have a number of classes that derive from a pure virtal base:
class base {
public:
virtual int f() = 0;
};
class derived_0 : public base {
public:
int f() {return 0;}
};
class derived_1 : public base {
public:
int f() {return 1;}
};
I only put two derived classes for brevity, but in practice I have more.
And I would like to create a class that has a const shared pointer to the base. I would like do to the following but I can't as I must initialize the const pointer in the initialization list:
class C{
public:
C(bool type) {
if(type) {
derived_0* xx = new derived_0;
x = shared_ptr<base>( xx );
}
else {
derived_1* xx = new derived1;
x = shared_ptr<base>( xx );
}
}
private:
const share_ptr<base> x;
};
How can I get this functionality?
You encapsulate the creation of the object in a function, like this:
shared_ptr<base> create_base(bool type) {
if(type) {
return make_shared<derived_0>();
}
else {
return make_shared<derived_1>();
}
}
And then you can use it in your initialization-list:
class C{
public:
C(bool type)
: x(create_base(type))
{}
private:
const share_ptr<base> x;
};
In simple cases like this precise example:
class C
{
shared_ptr<Base> const x;
public:
C( bool type )
: x( type
? static_cast<Base*>( new Derived_0 )
: static_cast<Base*>( new Derived_1 ) )
{
}
};
(And yes, the static_cast, or at least one of them, are necessary.)
In more general cases, where the decision logic is more complex, you
might want to create a static function which returns the shared_ptr,
e.g.:
class C
{
shared_ptr<Base> const x;
static shared_ptr<Base> makeSharedPtr( bool type );
public:
C( bool type )
: x( makeSharedPtr( type ) )
{
}
};
This will allow any imaginable logic (and a more complex set of
parameters as well).
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); }
};
I have the following structure:
class Base {
virtual T foo() = 0;
};
class Derived : public Base {
T foo() override { /**/ }
}
class Derived1 : public Base {
T foo() override { /**/ }
}
I need the following to work (or an adequate substitute):
some_container<unique_ptr<Base>> objects;
Basically,
C++ AMP doesn't allow for virtual functions in kernels, but I definitely need an inheritance chain-like container behaviour.
What is a recommended / common pattern to transform this sort of inheritance chain to template magic?
The canonical method to remove a vtable call is to replace it with a switch statement:
enum type_e
{
type_derived,
type_derived1
};
class Base
{
public:
Base( type_e type ) : m_type( type ) {}
T foo();
private:
type_e m_type;
};
T Base::Foo()
{
switch( m_type )
{
case type_derived:
return //{...} your Derived::Foo()
case type_derived1:
return //{...} your Derived1::Foo()
}
}
The only change in the API is that instead of call new Derived() you must call new Base( type_derived ). The major disadvantage is that you now have to hold all of your additional data (formerly members of Derived1 or Derived) in Base, which may bloat the class. On the other hand you can now make a container of Base by value, and avoid the overhead of std::unique_ptr.
You could roll your own, manual vtable emulation:
class Base {
protected:
using fp_t = int(*)(Base*);
fp_t fp;
Base( fp_t p ) : fp( p ) {}
public:
int foo() { return (*fp)(this); }
};
class Derived : public Base {
static int sfoo(Base* b) { return static_cast<Derived*>(b)->foo(); }
int foo() { return 42; }
public:
Derived() : Base(&sfoo) {}
};
Live example
I want to create 2 kind of classes.
the classes will have similar function "set", but the set funct will get "int" in class B and double in class C. (A is abstract calss but it does not require).
What do I need to do?
class A{
int x;
public:
A (int t=1): x(t){}
virtual void set ()=0;
}
class B: public A{
int y;
public:
virtual void set (int y);
};
class C: public A{
double y;
public:
virtual void set (double y);
};
void main ()
{
B b; //error
C c; //error
}
Create a single template class and instantiate which ever you need at the time, or typedef B and C from the template class:
template< typename T > class A
{
public: A() : mValue() {}
void Set( T value ) { mValue = value; }
private: T mValue;
};
typedef A< int > B;
typedef A< double > C;
There are pretty many variants to solve this, but first of all, virtual function has to have the same signature (there could be an exception, but that's irrelevant for your case). So solution is to have and argument(s) that will solve all cases. There are variants:
Pass all variants to the function, and use only particular one:
class A {
public:
virtual void set( int, double ) = 0;
};
class B {
int y;
public:
virtual void set( int val, double ) { y = val; }
};
class C {
double y;
public:
virtual void set( int , double val ) { y = val; }
};
This is not very good solution and does not scale well, so we can use union:
Union Arg {
int i;
double d;
};
class A {
public:
virtual void set( Arg a ) = 0;
};
// derived classes are trivial, so omitted
Union is not type safe, so we can use boost::variant instead
Another solution to have another hierarchy for parameter:
struct Arg {
virtual ~Arg();
};
struct IntArg : Arg {
int m_value;
};
struct DoubleArg : Arg {
double m_value;
};
class A {
virtual void set( const Arg &a ) = 0;
};
class B {
int y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const IntArg &>( a ).m_value; }
};
class C {
double y;
public:
virtual void set( const Arg &a ) { y = dynamic_cast<const DoubleArg &>( a ).m_value; }
};
You can use static_cast and then you will not need virtual destructor in Arg, but that is less safe.
These are only some variants, there could be much more, which one suits you best you can only decide based on your program requirements.
Ditch the inheritance and virtual thing. You can't easily access a statically unknown type result via a virtual function. So:
class A
{
private:
int x_;
public:
A( int const t = 1 ): x_( t ) {}
};
class B
: public A
{
private:
int y_;
public:
void set( int const y );
};
class C
: public A
{
private:
double y_;
public:
void set( double const y );
};
int main ()
{
B b; // OK
C c; // OK
}
Note the semicolon at the end of class A and the int main instead of void main.
Such details matter.
Otherwise you can send people who want to help you, on long wild goose chases. And you don't want that, do you? So, make sure the code you post has been accepted by a compiler, except possibly for the troublesome parts that you want to show do not compile.
The trick is to find common parts of B and C, and put them to base class. The stuff that is different should go to constructor parameter of the derived class:
class A {
virtual std::string get() const=0;
virtual void set(std::string s)=0;
};
class B : public A { B(int a) : a(a) { } int a; };
class C : public A { C(float b) : b(b) { } float b; }
To implement the functions, you'll need the following:
void B::set(std::string s) {
stringstream ss(s);
ss >> a;
}
void C::set(std::string s) {
stringstream ss(s);
ss >> b;
}
The functions look the same, but are actually calling different operator>>.
I'm writing a wrapper around some autogenerated classes to provide a better interface. I've written a simplified example to demonstrate the problem.
I have a class A which has a pointer to an object of class X, then I have class B (inherits A) which has a pointer to an object of class Y (inherits X).
That's all fine, except that I'm unsure what the best way is to store the pointers to X and Y. I need to be able to manipulate collections of objects of class A and B as if they were all A (with pointers to X being all I'd need there), which works fine with my example below.
My actual question is how best to handle the case of class B which needs to manipulate class Y objects rather than class X. I'm sure there is something quite obvious that I'm missing which I could use here. It feels clumsy to have to repeatedly cast this variable every time I use it and define a method with a different name (e.g. getY) for each class that inherits A that I create. There might be many methods like doStuff all of which would have to be calling getY.
class X {
private:
int i;
public:
X(int i) : i(i) {}
int getI() {
return i;
}
};
class Y : public X {
private:
int j;
public:
Y(int i, int j) : X(i), j(j) {}
int getJ() {
return j;
}
};
class A {
protected:
X* x;
public:
A(X* a) : x(a) {}
X* get() {
return x;
}
};
class B : public A {
public:
B(Y* y) : A(y) {}
private:
//I could create a new function for each class like class B
Y* getY() {
return (Y*)x;
}
public:
void doStuff() {
Y* y = getY();
y->getJ();
std::cout << "J: " << y->getJ() << cout::endl;
}
};
Extract from main:
X* x = new X(5);
Y* y = new Y(5,6);
B b(y);
b.doStuff();
One alternative which occurs to me is that when I construct class B I could initialise a pointer of type Y variable pointing at the same location as the one which be set in X. As long as my pointers were const I think that should be safe from the two references ever pointing to different things.
Any ideas most welcome.
Thanks.
Well, the first thing I would do is break the inheritance relationship between A and B. You say they have a common interface, so start by defining this interface:
class ILibraryWrapper {
public:
virtual X * get() = 0;
};
I assume that A and B share a lot of code (hence the inheritence relationship), so next define a template class to implement the interface and define the common bits:
template <class T> class LibraryWrapper : public ILibraryWrapper {
protected:
T * pointer;
public:
LibraryWrapper( T * value ) : pointer( value ) {}
virtual X * get() override { return static_cast<X *>( this->pointer ); }
};
Finally, define A and B like so:
class A : public LibraryWrapper<X> {
public:
A( X * value ) : LibraryWrapper( value ) {}
};
class B : public LibraryWrapper<Y> {
public:
B( Y * value ) : LibraryWrapper( value ) {}
void doStuff() {
std::cout << "J: " << this->pointer->getJ() << cout::endl;
}
};
Virtually all your code should then deal with ILibraryWrapper pointers or references. If some code absolutely must know the concrete type of the wrapped object, then you can do a dynamic cast:
auto wrapper = dynamic_cast<LibraryWrapper<Y> *>( object );
if( wrapper != nullptr ) {
// ...
}
But generally speaking, it's better to provide all needed functionality in the ILibraryWrapper interface.
As long as Y derives from X, and B derives from A, then this is easy.
Virtual functions can differ by return type as long as those return types are polymorphic. Implement the following in A:
virtual X* Get() const { return x; }
And the following in B:
virtual Y* Get() const { return static_cast< Y* >( A::Get() ); }
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;
}