I have two classes A (base) and B (deriving from A):
class A { };
class B : public A
{
int data;
public:
int get_data() { return data; }
};
Now I have a function test which takes base class pointer and calls derived class function :
void test(A * ptr)
{
ptr->get_data();
}
But problem is ptr may point to A's object or B's object. If it points to B's object, then OK, but if to A's object, then it is a problem.
Moreover, I don't want to make get_data() virtual because data is not property of A's object.
How can I check if ptr points to B's object? One solution which I can think is dynamic_cast and check it for NULL. Is it the best solution or can I have a better solution ?
This means your test function is lying. It is saying that it will accept a pointer to any A object, even types derived from A, but the function won't actually work for anything other than B. You're much better off taking a B*:
void test(B* ptr)
{
ptr->get_data();
]
If you can change the interface of A and B (including adding virtual functions) and if you can re-shuffle the code in the test function you can use the "visitor pattern". Here's a sample using the better named Base and Derived classes:
class Visitor
{
public:
void Visit(Base * B)
{
}
void Visit(Derived * D)
{
int data = D->get_data();
}
};
class Base
{
public:
virtual void Accept(Visitor * V )
{
V->Visit(this);
}
};
class Derived: public Base
{
public:
int get_data()
{
return data;
}
virtual void Accept(Visitor * V )
{
V->Visit(this);
}
private:
int data;
};
This way you can iterate over your vector of Base*, call Accept of each element and know that only for Derived elements the get_data method will be called.
Inheritance models the is-a relationship. Clearly in your code B is not an A and inheritance is the wrong model. You mention in your comment that you have a vector which is being passed to an enclosing, bigger, function. I would suggest that one of the following would be a better fit:
1. std::vector<boost::any>
2. std::vector<boost::variant<A,B>>
Edit
Here's an example using boost variant:
class A
{
public:
void DoIt()
{
std::cout << "did it!" << "\n";
}
};
class B
{
public:
void GetIt()
{
std::cout << "got it!" << "\n";
}
};
typedef boost::variant<A,B> ab_t;
typedef std::vector<ab_t> list_ab;
void test(list_ab& list)
{
std::for_each(std::begin(list), std::end(list), [](ab_t& item)
{
if(A* a = boost::get<A>(&item))
a->DoIt();
if(B* b = boost::get<B>(&item))
b->GetIt();
});
}
You say that actually you have a vector of elements A or B, then your test function really looks like:
void test( A ** ptr )
Then you can use the overloading C++ capabilities to make a utility function, the right function will be called:
void test( A ** ptr ) {
A * elem;
int i=0;
elem = ptr[i++];
while(elem) {
testElement(elem);
elem = ptr[i++];
}
}
void testElement( A * ptr ) { }
void testElement( B * ptr ) {
ptr->get_data();
}
Related
Given a code below
class Base {
public:
virtual void callThisOnce();
};
class Derived_A: public Base {};
class Derived_B: public Base {};
void function(std::vector<shared_ptr<Base>> v) {
for (auto i : v)
i->callThisOnce();
}
Vector v contains either or both shared_ptr<Derived_A> and shared_ptr<Derived_B> objects.
What I want to archive is that when ever function is called, if in v there is a object belong to class Derived_A, Derived_A::callThisOnce should be executed once; and if there is a object belong to class Derived_B, Derived_B::callThisOnce should be executed once.
I need a coding pattern that make it easiest to create Derived_C.
I tried this
class Derived_A: public Base {
virtual void callThisOnce(){
if(!_mutex.try_lock())
return;
/* Do something */
}
static std::mutex _mutex;
};
void function(std::vector<shared_ptr<Base>> v) {
for (auto i : v)
i->callThisOnce();
Derived_A::_mutex.try_lock(); // this call prevent undefined behavior of mutex::unlock
Derived_A::_mutex.unlock();
}
This pattern make me create a static mutex an required me to call std::mutex::unlock of all class. But it's seem to leave many problems.
Is there a better method to archive the same?
std::vector<Base> v
vector v contains either or both Derived_A and Derived_B objects.
What you describe isn't possible. A vector of Base can only contain objects of type Base and not objects of type Derived_A or Derived_B.
If you want polymorphic storage, then you need indirection. And if you want to combine indirection with the lifetime of the vector, then you need smart pointers. And if you want unique ownership, then you need a virtual destructor:
struct Base {
virtual void callThisOnce();
virtual ~Base() = default;
};
struct Derived_A: Base {};
struct Derived_B: Base {};
void function(std::vector<std::unique_ptr<Base>>& v);
To call a member function once per unique dynamic type, you could store each encountered std::type_index in a set and call the function only for the first one:
std::unordered_set<std::type_index> types;
for (auto&& ptr : v) {
auto [it, first] = types.emplace(typeid(*ptr));
if (first) {
ptr->callThisOnce();
}
If I got your intention right one way to achieve this is by combining runtime polymorphism (the correct function gets called) with using a static variable in each class (to track down if function is called only once per class and not per object):
class Base {
public:
virtual void callThisOnce() {
if (!base_called) {
std::cout << "Base::callThisOnce" << std::endl;
base_called = true;
}
};
static bool base_called;
};
class Derived_A: public Base {
public:
virtual void callThisOnce() override {
if (!deriveda_called) {
std::cout << "Derived_A::callThisOnce" << std::endl;
deriveda_called = true;
}
}
static bool deriveda_called;
};
class Derived_B: public Base {
public:
virtual void callThisOnce() override {
if (!derivedb_called) {
std::cout << "Derived_B::callThisOnce" << std::endl;
derivedb_called = true;
}
}
static bool derivedb_called;
};
bool Base::base_called;
bool Derived_A::deriveda_called;
bool Derived_B::derivedb_called;
void function(const std::vector<Base*> &v) {
Base::base_called = false;
Derived_A::deriveda_called = false;
Derived_B::derivedb_called = false;
for (auto i : v)
i->callThisOnce();
}
int main() {
std::vector<Base*> v;
Base b1, b2;
Derived_A da1, da2;
Derived_B db1, db2;
v.push_back(&b1);
v.push_back(&b2);
v.push_back(&da1);
v.push_back(&da2);
v.push_back(&db1);
v.push_back(&db2);
function(v);
return 0;
}
which will output:
Base::callThisOnce
Derived_A::callThisOnce
Derived_B::callThisOnce
EDIT:
The static variables should get reset after the callThisOnce calls to avoid some unwanted behaviour with recursive calls of function (thanks to #Jarod42)
void function(const std::vector<Base*> &v) {
for (auto i : v)
i->callThisOnce();
Base::base_called = false;
Derived_A::deriveda_called = false;
Derived_B::derivedb_called = false;
}
I'm working on a small project, and I found myself in a situation like this :
class A{}
class B : class A {
public:
void f();
int getType() const;
private:
int type;
}
class C : class A{
public:
int getType() const;
private:
int type;
}
I want to know if there's a way to call the f() function (in class B) from an object of type A?
I tried this but it says function f() cannot be found in class A :
int main(){
vector<A*> v;
// v initialized with values of A ...
if (v->getType() == 1){ // 1 is the type of B
v->f();
}
}
As you've seen, this code won't compile because A doesn't have an f method. In order to make it work, you'd have to explicitly downcast the pointer:
B* tmp = dynamic_cast<B*>(v);
tmp->f();
To begin with, with your current classes, you can't call getType() on an A*. Because the interface of A doesn't have this method. To solve this problem, you either need to make getType a virtual function in A, or move the type field to base class A (as protected) and initialize it in the constructors of the child classes. Let me show you the first method, because I think it is a better approach, since it makes the objective of this function more clear.
class A {
public:
virtual int getType() { return 0; } // or delete the function: ... getType() = 0;
}
class B : public A {
public:
int getType() override { return 1; }
}
With these classes, once you create an instance of B, getType() returns 1 when called on that instance, whether it is pointed to by an A* or B*:
A *object = new B();
object->getType(); // returns 1
Now, if you need to access the f() from B, you can again add it as a virtual method to A's interface, or make a cast to B*.
Using a virtual method:
class A {
public:
virtual void f() { /* a default action maybe? */ }
}
class B : public A {
public:
void f() /* override if you want */ { /* whatever this function does in B */ }
}
...
for (A *ptr : v)
ptr->f();
Using a cast:
class A {
public:
virtual int getType() { return 0; }
}
class B : public A {
public:
void f();
int getType() override { return 1; }
}
...
for (A *ptr : v)
if (ptr->getType() == 1)
dynamic_cast<B*>(ptr)->f();
I understand how C++ solves the diamond problem in multiple inheritance by using virtual inheritance. Suppose the following situation:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C : public A {
void fooc() { int x = get_num(); }
};
class D : public B, public C {
void food() { int x = get_num(); }
};
The get_num() call is ambiguous inside food(). I know I can fix it either by calling A::get_num() or by virtual inheritance using virtual public A. But I can see a third approach:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C { // won't inherit from A anymore
const A& base; // instead keeps a reference to A
void fooc() { int x = base.get_num(); }
public:
explicit C(const A* b) : base(*b) { } // receive reference to A
};
class D : public B, public C {
void food() { int x = get_num(); }
public:
D() : C(this) { } // pass "this" pointer
};
The external code doesn't need to consider C as an A.
Considering it has no impacts on my particular class hierarchy design, are there any advantages of the third approach over the virtual inheritance way? Or, in terms of cost, it ends up being the same thing?
Congratulations ! You've just re-invented the principle of composition over inheritance !
If this works with your design, it means that C was in fact not a kind of A, and there was no real justification to use inheritance in first place.
But don't forget the rule of 5 ! While your approach should work in principle, you have a nasty bug here : with your current code, if you copy a D object, its clone uses the wrong reference to the base (it doesn't refer to it's own base, which can lead to very nasty bugs...
Demo of the hidden problem
Let's make A::get_num() a little bit more wordy, so that it tells us about the address of the object that invokes it:
int get_num() const {
cout << "get_num for " << (void*)this <<endl;
return num;
}
Let's add a member function to C, for the purpose of the demo:
void show_oops() { fooc(); }
And same for D:
void show() { food(); }
Now we can experiment the problem by running this small snippet:
int main() {
D d;
cout<<"d is "<<(void*)&d<<endl;
d.show();
d.show_oops();
D d2=d;
cout<<"d2 is "<<(void*)&d2<<endl;
d2.show();
d2.show_oops();
}
Here an online demo. You will notice that d2 does produce inconsistent results, like here:
d is 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
d2 is 0x7fffe0fd11b0
get_num for 0x7fffe0fd11b0
get_num for 0x7fffe0fd11a0 <<< OUCH !! refers to the A element in d !!
Not only do you refer to the wrong object, but if the d object would decease, you would have a dangling reference, so UB.
Is it possible to pass this by default ?
Here is what I currently have
class A
{
public:
template<typename T>
void dowithT(T t) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
a.dowithT(this);
}
};
This function requires passing this from the caller of the function every time. So I wondered if there is a way to encapsulate this task, so that you don't need to pass this to dowithT.
I tried to do something like this:
class A
{
public:
// '= this' doesn't compile
template<typename T>
void dowithT(T t = this) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' without 'this'
a.dowithT();
}
};
Unfortunately, I can't use templates, so my first solution isn't an option.
Is this possible?
Edit: I gave a concrete answer with my own implementation below. Also with a few mor deatils of what I wanted in the end.
TL;DR No, this is not possible.
this is not the same type in every class, you can't generalize it, so no, not possible.
Additionally, what would this be if doWithT() was called from a non-member function? nullptr?
That's why it isn't possible. You have to use a template.
Instead of B having a member of type A, it can inherit from A, and use something like the "curiously recurring template pattern."
If you cannot make class A a template, you can still do it like so:
class A
{
protected:
template <class T>
void dowithT()
{
T* callerthis = static_cast<T*>(this);
// callerthis is the "this" pointer for the inheriting object
cout << "Foo";
}
};
class B : public A
{
public:
B()
{
dowithT<B>();
// Or A::dowithT<B>();
}
};
dowithT() must only be called by an inheriting class (hence I made it protected), with the template parameter the caller's own type, or you'll break everything.
You may achieve exactly what you want by using a private mixin class to provide the dowithT method that takes no arguments:
#include <iostream>
#include <typeinfo>
class A
{
public:
template<typename T>
void dowithT(T* t) {
std::cout << "Hello, World" << typeid(*t).name() << std::endl;
}
};
template<class Owner>
struct calls_a
{
void dowithT()
{
auto p = static_cast<Owner*>(this);
p->a.dowithT(p);
}
};
class B
: private calls_a<B>
{
friend calls_a<B>;
A a;
public:
B()
{
//Calling 'dowithT' with 'this'
dowithT();
}
};
int main()
{
B b;
}
No, it is not possible. There is nothing really special about this when used as an argument to a function taking T* (template or not), it's just a pointer like any other.
this A is different from this B. In your first code, this refers to the caller, while in the second this refers to the callee. Thus what you want to do isnt really possible.
Here's one possibility, which might, or might not suit your needs:
template<typename T>
class A
{
public:
A(T t) : t(t) {}
void dowithT()
{
cout << "Foo";
}
private:
T t;
};
class B
{
public:
A<B*> a;
B() : a(this)
{
a.dowithT();
}
};
You could use a private method in class B that acts as a relay, and use the constant nullptr as a special value for this, if you want to be able to pass other values:
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
innerdo();
}
private:
void innerdo(B *p = nullptr) {
if (p == nullptr) p = this;
a.dowithT(p);
}
};
If you only need to pass this it is even simpler
void innerdo() {
a.dowithT(this);
}
After trying out various things you mentioned, I'd like to give my answer/solution to the problem myself to clarify some details:
#include <iostream>
using namespace std;
#include <functional>
template <typename CallerType>
class AFunctionConstructor{
private:
virtual void abstr()
{}
public:
typedef void(CallerType::*CallerTypeFunc)();
function<void()>* constructFunction(CallerTypeFunc func)
{
CallerType* newMe = dynamic_cast<CallerType*> (this);
return new function<void()>(std::bind(func,newMe));
}
};
class A : public function<void()>
{
protected:
public:
A();
A(function<void()>* func) : function<void()>(*func)
{}
};
// now create ressource classes
// they provide functions to be called via an object of class A
class B : public AFunctionConstructor<B>
{
void foo()
{
cout << "Foo";
}
public:
A a;
B() : a(constructFunction(&B::foo)) {}
};
class C : public AFunctionConstructor < C >
{
void bar()
{
cout << "Bar";
}
public:
A a;
C() : a(constructFunction(&C::bar)) {}
};
int main()
{
B b;
C c;
b.a();
c.a();
cout << endl;
A* array[5];
array[0] = &b.a; //different functions with their ressources
array[1] = &c.a;
array[2] = &b.a;
array[3] = &c.a;
array[4] = &c.a;
for (int i = 0; i < 5; i++) //this usability i wanted to provide
{
(*(array[i]))();
}
getchar();
return 0;
}
Output :
FooBar
FooBarFooBarBar
This is as far as i can press it down concerning examples. But i guess this is unsafe code. I stumbled across possible other and simpler ways to achieve this (other uses of std::function and lambdas(which i might have tried to reinvent here partially it seems)).
At first I had tried to pass "this" to the bind function in function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)
,though, which i now get through the dynamic upcast.
Additionally the functionality of AFunctionConstructor was first supposed to be implemented in a Constructor of A.
Scenario: I have the following defined classes.
class Baseclass { };
class DerivedTypeA : public Baseclass { };
class DerivedTypeB : public Baseclass { };
// ... and so on ...
class Container
{
list<Baseclass*> stuff;
list<DerivedTypeA*> specific_stuff;
// ... initializing constructors and so on ...
public:
void add(Baseclass * b)
{
stuff.add(b);
}
void add(DerivedTypeA * a)
{
stuff.add(a);
specific_stuff.add(a);
}
};
class ContainerOperator
{
Container c;
// ... initializing constructors and so on ...
public:
void operateOnStuff(Baseclass * b)
{
// This will always use "void add(Baseclass * b)" no matter what object b really is.
c.add(b);
}
};
// ...
containerOperator.operateOnStuff(new DerivedTypeA());
So, what I want to do is to handle a certain derived class in some special way in Container.
Problem: void add(DerivedTypeA * a) is never called. I'm obviously doing something wrong. What is the correct way of doing what I am trying to achieve here?
Overload resolution in C++ happens at compile-time, not run-time. The "usual" way to solve problems like this is to use Visitor pattern.
You can reduce the amount of boilerplate copy-paste by implementing Visitor with CRTP.
If you use CRTP for Base::accept, you don't need to define it any more in derived classes.
Here is a similar program to yours, but a little simpler:
#include <iostream>
class Base; class Derived;
struct Operation {
void add(Base *b) {
std::cout << "Base\n";
}
void add(Derived *b) {
std::cout << "Derived\n";
}
void visit(Base *b); // need to define this after Base class
};
struct Base {
virtual ~Base() {}
virtual void accept(Operation &o)
{
o.add(this);
}
};
void Operation::visit(Base *b) {
b->accept(*this);
}
struct Derived : public Base {
void accept(Operation &o)
{
o.add(this);
}
};
int main() {
Operation o;
Base b;
Derived d;
Base *ptrb = &b;
Base *ptrd = &d;
o.add(ptrb); // These two print "Base"
o.add(ptrd);
o.visit(ptrb); // "Base"
o.visit(ptrd); // "Derived"
}
You can use RTTI to determine whether the provided object is of the derived type, and if so, call the second add() function.
void add(Baseclass * b)
{
stuff.add(b);
DerivedTypeA * a = dynamic_cast<DerivedTypeA *>(b);
if ( a != 0 )
specific_stuff.add(a);
}
Unlike the visitor pattern this solution violates the Open-Closed Principle, but it's a lot simpler and easier to understand when the number of derived classes do not change or change slowly over time.