Say I have two classes, ClassA and ClassB.
ClassB inherits ClassA, and has some additional functions and variables.
Is it possible for me to make a function that can accept either ClassA or ClassB as the same argument, and let me determine which one was used?
Yes, you can take the parameter by reference:
void foo(ClassA& x) //or const ClassA
You'll be able to pass both instances of ClassA or ClassB, and use RTTI to determine which type it actually is inside the function.
Alternatively, you can pass a pointer to ClassA, but references are to be preferred where possible.
Declare the function parameter to be a pointer or a reference to an ClassA instance (don't pass it by value or the input instance will get sliced at runtime). Then you can use dynamic_cast if you need to access ClassB-specific functionality. For example:
class ClassA
{
public:
int a;
virtual ~ClassA() {}
void DoSomething();
};
class ClassB : public ClassA
{
public:
int b;
void DoSomethingElse();
};
void func(ClassA *obj)
{
int a = obj->a;
obj->DoSomething();
ClassB *objB = dynamic_cast<ClassB*>(obj);
if (objB)
{
int b = objB->b;
objB->DoSomethingElse();
}
}
int main()
{
ClassA a;
func(&a);
ClassB b;
func(&b);
return 0;
}
Here's an idea with a bit of indirection. The function Consumer::accept accepts both objects of type A and type B, and the specific behaviour is implemented by those classes rather than by your consumer.
struct Consumer;
struct A
{
virtual ~A() { }
virtual int use(Consumer &);
};
struct B : A
{
virtual int use(Consumer &);
};
struct Consumer
{
void accept(A & x)
{
int n = x.use(*this);
do_more_stuff(n);
}
void do_more_stuff(int);
// ...
};
Related
Here is what UML looks like CLASS UML
ClassA has an pointer to ClassB, and ClassB has a pointer to ClassC. I was wondering if I can access functions of ClassA in ClassC without inheriting ClassA.
Q: I was wondering if I can access functions of ClassA in ClassC without inheriting ClassA.
A: Yes, it is possible to access functions of ClassA in ClassC. Either by calling static member functions of classA or by providing specific instance of classA to ClassC. It may look like that classA can be accesed by following the pointers in reverse direction (ClassC to ClassB to ClassA) but that is not possible. Pointers point to values only in one direction.
This is interesting question about differences between a class and instances of class (objects). The following example shows why there is no classA::callAnyMethod():
#include <iostream>
class B;
class C;
class A
{
public:
A(B *next, int value) : next_(next), value_(value) { }
void af1() const { std::cout << value_ << "\n"; }
static void af2() { std::cout << staticValue << "\n"; }
protected:
B *next_;
int value_;
static int staticValue;
};
int A::staticValue = 3;
class B
{
public:
B(C *next) : next_(next) { }
protected:
C *next_;
};
class C
{
public:
void cf1(const A &a) { a.af1(); }
void cf2() { A::af2(); }
};
int main()
{
C c;
B b(&c);
A a1(&b, 1);
A a2(&b, 2);
// a1 is first instance of class A.
// One 'A::value_' is defined in a1 and is equal to 1.
c.cf1(a1);
// a2 is second instance of class A.
// Second 'A::value_' is defined in a2 and is equal to 2.
c.cf1(a2);
// Without specific instance of class A, we can use only static member
// 'A::staticValue' which is defined at file scope and is equal to 3.
// 'A::staticValue' is not part of objects (instances) of class A.
c.cf2();
return 0;
}
I have two derived classes as follows. This is the simplified design version that I have right now.
class A objects are copy-able but they are big. That is why I used reference in the constructor of the derived_1 class.
I used shared_ptr for the class derived_2 in order to make usage of p_a optional. I noticed that I can also use std::optional in the constructor of the class derived_2. By this I can give hint to the user that this argument is indeed optional.
Please take into consideration that this the simplified version and this member p_a is used in all three classes intensively. Also std::shared_ptr<A&> a is not the only argument for the constructor in the real example. I will be thankful if you show me how to use std::optional properly here.
Is it ok to mix std::optional with std::shared_ptr?
class A
{
int m_a;
public:
A(int a) :m_a(a) {};
};
class Base
{
protected:
std::shared_ptr<A> p_a; //Do I need to change type of p_a???
public:
Base() {};
void print()
{
if (p_a)
std::cout << "p_a is allocated\n";
}
void virtual check() = 0;
};
class derived_1 : public Base
{
public:
derived_1(const A& a)
{
p_a = std::make_shared<A>(a);
}
void check() {};
};
class derived_2 : public Base
{
public:
derived_2(std::shared_ptr<A&> a) //can I use std::optional instead??
{
if (a)
p_a = a;
}
void check() {};
};
when a base class pointer points to the object of it's derived class and if a function being overridden we use virtual function to solve the problem . So that we can access the own function of derived class using the pointer.
Like this , i was thinking that if there a way which can be applied on virtual keyword in variable , so that we can access the latest version of a variable in derived class using pointer.
#include <iostream>
using namespace std;
class base
{
public:
int x;//but what about this , if we add virtual keyword here.
//it will give error if trying to do so .
//but can you tell me what can i do if i want to make use of it as virtual function
//if not please tell me why
virtual void display(void) //to call the recent version of display function we make use of virtual here
{
cout << "base\n";
}
};
class derived : public base
{
public:
int x;
void display(void)
{
cout << "derived\n";
}
};
int main(void)
{
base *p;
base ob1;
derived ob2;
p=&ob2;
p->x=100;//here i want to set 100 to the x of derived class not that x which has been inherited
//But it sets to the x of base class which i dont wanted
p->display();//here we can access the latest version of display function in derived class
return 0;
}
Please, No body ask me why i want to do so.I don't have any intention to do in my real code. i asked for the curiosity.
No, you cannot use virtual for fields, only for methods.
However you can simulate that by creating a function that returns a reference to a field:
class Base
{
private:
int x;
public:
virtual int& X() { return x; }
};
class Derived : public Base
{
private:
int x;
public:
virtual int& X() override { return x; }
};
int main()
{
Derived d;
Base* b = &d;
b->X() = 100; // will set d's x
}
You can't override member variables with the virtual keyword. You could, however, have virtual getters and setters that refer to different member variables in the base and derived classes to achieve a similar effect:
class base {
public:
virtual int getX() {
return x;
}
virtual void setX(int x) {
this->x = x;
}
private:
int x;
}
class derived : public base {
public:
int getX() {
return x;
}
void setX(int x) {
this->x = x;
}
private:
int x;
}
The other answers are totally fine but you can also use the much simpler syntax:
class base {
public:
virtual operator int&() { return x; };
virtual operator int() { return x; };
protected:
int x;
};
if you have a single variable that you'd wish to virtualize in your class.
The second declaration is only to avoid using a reference when you just need the value, while when assigning the reference is automatically chosen for you.
You can override these operators at will from classes derived from base.
class derived : public base {
public:
operator int() override { return x * 5; };
}
I understand that the following code doesn't work -- can't convert base to foo.
Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?
What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.
class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
base* b = new foo();
method(*b);
}
The easiest way is probably to just make method() a virtual member function on foo:
class base {
public:
virtual void method() const = 0;
};
class foo : public base {
public:
void method() const override { }
};
int main(){
foo f;
base* b = &f;
b->method();
}
But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.
The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.
In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:
class base {
public:
virtual void dispatch() const = 0;
};
class foo : public base {
public:
void dispatch() const override;
};
void method(const foo& f){}
void foo::dispatch() const {
method(*this);
}
int main(){
foo f;
base* b = &f;
b->dispatch();
}
You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.
Use virtual functions to solve these kinds of problems:
class base {
public:
virtual void func() const { /* A */ }
};
class foo : public base {
public:
void func() const override { /* B */ }
};
void method(const base& f) {
f.func();
}
int main(){
base* b = new foo();
method(*b);
}
Now, depending on the actual type of f, either A or B code will be executed in method.
Suppose an object of class B is a member of class A.
class B{
//Definitions
}
class A{
public:
A();
B b_child;
int some_function();
}
One of the functions defined inside B needs to call a (public) function from its owner (parent?) A. Is there an immediate way to do this?
The only way I've managed to do this so far was to implement it outside the classes' definitions:
A a_obj;
a_obj.b_child.setowner(&aobj);
which tells b_child who is its owner. I don't like this. I'd rather use some builtin method for b_child to access its parent (if possible). If that's not possible, I'd rather pass the owner's address directly in the constructor for B, but I don't know how to reference A's address inside its definition.
There is no builtin method to get the 'owner' of a variable, whatever that means. Your approach of setting the owner is correct. Furthermore, doing so in the construction of B is also a correct decision. Sample code:
class B
{
public:
explicit B( A* owner ) : _owner( owner ) {}
...
private:
A* _owner;
};
class A
{
public:
A() : _child( this ) {}
...
private:
B _child;
};
Note some compilers may give you a warning for using this in that context, but its ok for the current example. Just make sure you don't call any A member functions from within B constructor, since the pointer you get still points to an unconstructed object at that stage.
I'd rather use some builtin method for b_child to access its parent (if possible).
No, it's not.
but I don't know how to reference A's address inside its definition.
You can use this pointer.
A() : b_child(this) { }
You should use this pointer to refer to the object within itself
class B{
//Definitions
}
class A{
private:
B b_child;
public:
A()
{
b_child.set_owner(this);
}
}
You should define B like the following:
template <class T, int N>
class B
{
public:
int example_func() { return static_cast<T&>(*this).some_function(); }
};
And then make B<A> a subclass of A (so it can call A directly).
class A : protected B<A,0>, protected B<A,1>
{
A();
int some_function() { return 42; }
};
This is called the curiously recurring template pattern.
If you don't want B to be a template class, and you're only going to use B with A, then the following is fine:
template <int N>
class B
{
public:
int example_func() { return static_cast<A&>(*this).some_function(); }
};
class A : protected B<0>, protected B<1>
{
A();
int some_function() { return 42; }
};
Alternatively, if you want to use B with not just A, but don't want to make B a template class (say, if you want a collection of pointers to B), you can do the following:
template <int N>
class B
{
public:
int example_func() { return some_function(); }
virtual int some_function() = 0;
};
class A : protected B<0>, protected B<1>
{
A();
int some_function() { return 42; }
};
This will resolve the some_function() call at run-time, and require a virtual pointer to be stored in your class.