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>>.
Related
Is it possible to achieve behaviour demonstrated below with virtual functions? And if it's not the correct way to go about polymorphism then what would be the correct way in this example?
class Base_
{
float x;
float y;
float z;
public:
Base_(float xx=0, float yy=0, float zz=0)
{
x = xx;
y = yy;
z = zz;
}
virtual void SetParemeters(what here?)=0; //Different number of arguments
};
class Derived_1 :public Base_
{
float r;
public:
Derived_1(float rr=1, float xx=0, float yy=0, float zz=0):Base_(xx,yy,zz)
{
r=rr;
}
virtual void SetParemeters(float v1) //Different number of arguments
{
r=v1;
}
};
class Derived_2 :public Base_
{
float k;
float w;
public:
Derived_2(float kk=1, float ww=1,float xx=0, float yy=0, float zz=0):Base_(xx,yy,zz)
{
k=kk;
w=ww;
}
virtual void SetParemeters(float v1, float v2) //Different number of arguments
{
k=v1;
w=v2;
}
};
int main()
{
Derived_1 d1;
Derived_2 d2;
Base_ *ptr;
ptr = &d1;
ptr -> SetParemeters(one argument)
ptr = &d2;
ptr-> SetParemeters(one or two arguments)
return 0;
}
And even if I managed to achieve that, how can I set only second parameter (k) here: ptr-> SetParemeters(one or two arguments)?
I searched for answers but I only found answers to specific scenarios which made the whole thing difficult for me to understand.
Yes, make Base_::SetParameters takes two (optional) arguments:
class Base_
{
// [...]
public:
virtual void SetParemeters(float=0f, float=0f)=0;
};
Derived_1::SetParameters just ignores the first one:
class Derived_1 :public Base_
{
// [...]
virtual void SetParemeters(float v1, float=0f)
{
r=v1;
}
};
while Derived_2 takes the both of them
class Derived_2 :public Base_
{
// [...]
virtual void SetParemeters(float v1, float v2)
{
k=v1;
w=v2;
}
};
demo: https://coliru.stacked-crooked.com/a/c528ffff005df5b9
Note though, this significantly reduces the interest of virtual functions...
Derived_1 d1;
Derived_2 d2;
Base_ *ptr;
ptr = &d1;
ptr->SetParameters(one argument)
ptr = &d2;
ptr->SetParameters(one or two arguments)
The way how this code is written implies that you have knowledge about two things:
at the time of the first call to SetParameters(), ptr points to an object of type Derived_1
at the second call, it points to an object of type Derived_2.
This in turn means that you know the static types -- and in fact, you need to, due to the different signatures.
For such a scenario, dynamic polymorphism is not the right choice, because its premise is that you can talk to different implementations (overridden methods) using a uniform access (calling the virtual base method).
So, if you have this knowledge at compile time, simply use non-virtual method calls.
However, there are similar scenarios where you may actually be interested in supporting different signatures at runtime, for example if you load configuration dynamically. Here is an example, where not the number, but the types of arguments differ.
class Car : public Vehicle
{
virtual void addFuel(const Petrol& f) override;
};
class Airplane : public Vehicle
{
virtual void addFuel(const Kerosene& f) override;
};
How would then the base function look?
class Vehicle
{
virtual ~Vehicle() {} // don't forget this!
virtual void addFuel(const /* which type? */& f) = 0;
};
One option is to make the fuel type a hierarchy as well (both Kerosene and Petrol inherit the Fuel class):
class Vehicle
{
virtual ~Vehicle() {}
virtual void addFuel(const Fuel& f) = 0;
};
However, in this case, each implementation would need to either rely on the fact it's passed the right fuel, or check the type at runtime.
class Airplane : public Vehicle
{
virtual void addFuel(const Fuel& f) override
{
if (auto* k = dynamic_cast<const Kerosene*>(&f))
{
// use concrete fuel
}
}
};
You can make SetParameters a variadic function and have the polymorphic interface be internal, providing the writeable parameters in a generic form (here as a vector of pointers to them):
class Base_
{
float x;
float y;
float z;
public:
Base_(float xx=0, float yy=0, float zz=0)
{
x = xx;
y = yy;
z = zz;
}
virtual std::vector<float*> getAllExtraParameters() = 0;
template<class ... Ts>
void SetExtraParameters(Ts&& ... ts)
{
auto extras = getAllExtraParameters();
if (sizeof...(ts) > extras.size())
throw std::runtime_error("Too many parameters given!");
// Fold expression - could be implemented differently in C++ < 17.
int index = 0;
((*extras[index++] = ts), ...);
}
};
class Derived_1 :public Base_
{
float r;
public:
Derived_1(float rr=1, float xx=0, float yy=0, float zz=0):Base_(xx,yy,zz)
{
r=rr;
}
std::vector<float*> getAllExtraParameters() override
{
return { &r };
}
};
class Derived_2 :public Base_
{
public:
float k;
float w;
Derived_2(float kk=1, float ww=1,float xx=0, float yy=0, float zz=0):Base_(xx,yy,zz)
{
k=kk;
w=ww;
}
std::vector<float*> getAllExtraParameters() override
{
return { &k, &w };
}
};
Demo and tests: https://godbolt.org/z/ofXnuH
In multiple inheritance,where all the base class contains same function name with different functionality, we can access the protected function from particular base class using "::" scope resolution operator.
However, I tried something else. I created the objects of the base class in inside the child class. And tried calling the function using through object of that particular class.
But I was getting the following compiler error:
"‘void A::func(int&)’ is protected within this context."
Please let me know where did i go wrong.
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val(int new_val)
{
a = new_val;
a_val.func(a);
b_val.func(a);
c_val.func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
If you want to keep your code with the base classes as having independent functionality and still remaining protected the easiest way to resolve your issue is by slightly changing the name of your protected functions and adding a public function that calls the protected members: See these class declarations for example:
class A {
public:
void func( int& a ) {
func_impl( a );
}
protected:
void func_impl( int& a ) {
a = a * 2;
}
};
class B {
public:
void func( int& b ) {
func_impl( b );
}
protected:
void func_impl( int& b ) {
b = b * 3;
}
};
class C {
public:
void func( int& c ) {
func_impl( c );
}
protected:
void func_impl( int& c ) {
c = c * 5;
}
};
class D : public A, public B, public C {
public:
int a;
A a_val;
B b_val;
C c_val;
void update_val( int val ) {
a = val;
a_val.func( a );
b_val.func( a );
c_val.func( a );
}
void check( int );
};
void D::check( int val ) {
update_val( val );
std::cout << "Value = " << a << std::endl;
}
This provides a nice public interface to call the protected member functions. This also resolves the issue of accessing the protected members. When I run your program and input a value of 5 it returns a result of 150 and works as expected.
This snippet should show you how inheritance works and when you can and can not access protected members:
class DerivedA : public Base {
public:
Base b;
void call_message() {
b.message(); // Protected Member of Base class can not be accessed
}
};
class DerivedB : public Base {
public:
void call_message() {
message(); // This works without problem!
}
};
Just as I did above one way to resolve this is by adding a public interface caller to the protected implementation.
class Base {
public:
void message() {
message_impl();
}
protected:
void message_impl() {
std::cout << "This is a protected member of Base\n";
}
};
Now you can do this:
class DerivedA {
public:
Base b;
void call_message() {
b.message(); // Accessible through public interface.
}
};
When you are in your derived class, it has access to its own ancestor methods. But it doesn't have access to your variables member protected and private methods and variables.
Redesign your code, you are trying things and contorting the other classes design for bad reasons. Francis' code is a good solution, but D doesn't need to inherit from anything.
If you don't want to create another function, you can do something like this:
#include <iostream>
using namespace std;
class A
{
protected:
void func(int & a)
{
a = a * 2;
}
};
class B
{
protected:
void func(int & a)
{
a = a * 3;
}
};
class C
{
protected:
void func(int & a)
{
a = a * 5;
}
};
class D : public A,public B,public C {
public:
int a;
void update_val(int new_val)
{
a = new_val;
this->A::func(a);
this->B::func(a);
this->C::func(a);
}
void check(int);
};
void D::check(int new_val)
{
update_val(new_val);
cout << "Value = " << a << endl;
};
int main()
{
D d;
int new_val;
cin >> new_val;
d.check(new_val);
}
This works because, this refers to the current instance of class D, and it already inherits class A, class B, class C. So you can directly access the protected functions of the respective classes.
Remember: It will not work if you have not inherited the classes.
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); }
};
Let's say I have two classes, A and B:
class B;
class A
{
private:
int an_int;
B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
This solution is most probably what is intended in an exercise about inheritance where you can't use a forward declaration.
Instead of the forward declaration
class B;
you can define an interface like
struct I_whoop
{
virtual void whoop_whoop() = 0;
};
then let class B implement that interface, and just use a pointer to the interface.
Actually You can not if using concrete class.
But You can achieve your goal by using template parameters. Making class B a template parameter of template class A.
How can I make it so that I don't have to prototype B in order to have a pointer to a B object in class A?
Like this:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n) : an_int(n), something_else(nullptr) {}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n) : an_int(n), something_else(nullptr) {}
};
In C and C++ it has never been necessary for a type T to be
forward declared before the declaration of objects of type T *
(or const variants), because the declaration of a T * per se requires
the compiler only to know the size of a T *, not the size or definition
of a T, and the size of a T * is the same, regardless of T.
Here is a more fleshed-out illustration:
class A
{
private:
int an_int;
class B *something_else;
public:
A(int n, class B * pb = nullptr) : an_int(n), something_else(pb) {}
int get_int() const {
return an_int;
}
void set_B(class B * pb) {
something_else = pb;
}
class B * get_B() const {
return something_else;
}
};
class B
{
private:
int an_int;
class A *something_else;
public:
B(int n, class A * pa = nullptr) : an_int(n), something_else(pa) {}
int get_int() const {
return an_int;
}
void set_A(class A * pa) {
something_else = pa;
}
class A * get_A() const {
return something_else;
}
};
#include <iostream>
int main()
{
A a(1);
B b(2);
a.set_B(&b);
b.set_A(&a);
std::cout << a.get_B()->get_int() << std::endl;
std::cout << b.get_A()->get_int() << std::endl;
return 0;
}
Output:
2
1
(gcc 4.9.2/clang 3.5.2 -std=c++11 -Wall -pedantic)
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).