I want to call a member function of another class on an object, but I cant seem to figure out how this works. As example code on how it should work:
Class A {
void somefunction(int x);
}
Class B : A {
void someotherfunction(int x);
}
Class C {
void x() {
callY(&ofthefunction);
} //here you call the function, you dont have an object yet, and you don't know the argument yet, this will be found in function callY
void Y(*thefunction) {
find int x;
if(something)
A a = find a;
a->thefunction(x);
else
B b = find b;
b->thefunction(x);
}
}
I hope this makes sence, It is also possible to split this in 2 methods, Y1 and Y2, but seeing as 90% of the code is the same (finding things in a XML file), only the object and argument where to save it is different, i'd like to do this
You can use something known as a virtual function. By the way, your syntax is hideous, it's class not Class, you need braces for your conditionals, and a judicious application of public, some extra semicolons, etc. It would be appreciated if you would go near a compiler before coming here, y'know.
class A {
public:
virtual void somefunction(int x);
};
class B : public A {
public:
virtual void somefunction(int x);
};
void func(A& a) {
int x = 0;
// Do something to find x
a.somefunction(x);
// calls A::somefunction if this refers to an A
// or B::somefunction if it's a B
}
int main() {
A a;
func(a); // calls A::somefunction
B b;
func(b); // calls B::somefunction
}
What you want to do can be done, although I woudn't solve it this way:
class A {
public:
virtual int doit(int x) { return x+1; }
};
class B : public A {
public:
int doit2(int x) { return x*3; }
int doit(int x) { return x*2; }
};
int foo(int (A::*func)(int), int x, bool usea) {
if (usea) {
A a;
return (a.*func)(x);
} else {
B b;
return (b.*func)(x);
}
}
int main() {
int (A::*bla)(int) = &A::doit;
foo(bla, 3, true);
foo(bla, 3, false);
}
However, for this to work, the following has to be satisfied:
You must use function pointers of the base class (e.g. int (A::*bla)(int)), otherwise you won't be able to call it on that base class (e.g. int (B::*bla)(int) can only be used on B instances, not on A instances, even if the method is already defined in A).
The methods must have the same names as in the base class
To use overriding (e.g. different impl in derived class), you have to use virtual functions.
But I would rather rethink your design...
No, that won't work at all. A pointer to a member of A will always point to that function, even when it's called on B because B inherits from A.
You need to use virtual functions. I see DeadMG has beaten me to it.
Related
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.
Pretty sure this is an easy question, but I've just come over from the Ruby world where everything is unicorns and rainbows, and I need a serious reality adjustment. (I also suspect the title of this question is incorrectly worded, but I don't know the C++ terminology (yet) for what I'm asking.)
the question
In the following code, how can I get B::complex_method_on_x() use the value returned by B::x()? As it is, it is using the value returned by A::x(). (The printf()s should make it obvious what I'm expecting.)
the code
#include <stdio.h>
class A {
public:
int x() { return 42; }
int complex_method_on_x() { return 2 * x(); }
};
class B : public A {
public:
int x() { return 1; };
};
int main() {
A a;
B b;
printf("a.x() = %d (expect 42)\n", a.x());
printf("a.complex_method_on_x() = %d (expect 84)\n", a.complex_method_on_x());
printf("b.x() = %d (expect 1)\n", b.x());
printf("b.complex_method_on_x() = %d (expect 2)\n", b.complex_method_on_x());
return 0;
}
Running it, I get:
$ ./test_subclass
a.x() = 42 (expect 42)
a.complex_method_on_x() = 84 (expect 84)
b.x() = 1 (expect 1)
b.complex_method_on_x() = 84 (expect 2)
Specifically, in class B, I don't want to re-type the definition of complex_method_on_x(); I want to inherit that from the superclass. But I want complex_method_on_x() to call B's definition of x(); as it is, it is calling A's definition of x().
I don't want to make x() virtual, because then every subclass of A would have to define x(); I'd like to use the A's definition of x() if the subclass doesn't provide it.
#include <stdio.h>
class A {
public:
virtual int x() { return 42; }
int complex_method_on_x() { return 2 * x(); }
};
class B : public A {
public:
int x() { return 1; };
};
int main() {
A a;
B b;
printf("a.x() = %d (expect 42)\n", a.x());
printf("a.complex_method_on_x() = %d (expect 84)\n", a.complex_method_on_x());
printf("b.x() = %d (expect 1)\n", b.x());
printf("b.complex_method_on_x() = %d (expect 2)\n", b.complex_method_on_x());
return 0;
}
add virtual on A::x()
A superclass can access a subclass methods using virtual reserved keyword to declare an abstract functions.
class baseClass {
public:
baseClass(){
PrintClassName();
}
virtual void GetClassName()=0;
};
class subClass : public baseClass {
public:
virtual void GetClassName(){cout<<"buttonClass";}
};
Applied to your case:
class A {
public:
int complex_method_on_x() { return 2 * subclass_x(); }
virtual void subclass_x()=0;
};
class B:public A{
virtual void subclass_x(){return 1}
};
I'm not sure how this would work with C++, not knowing the language specifics myself, but I would think changing your code to be something along the lines of
int complex_method_on_x() { return 2 * self.x(); }
would do the trick. Basically, force the x() inside the complex_method_on_x() to refer to the calling class' definition of x(), rather than the locally scoped definition.
Please check the following code. Why it is wrong and how to fix? Thank you.
class A
{
public:
class B
{
public:
B(int(*cf)())
{
f = cf;
}
int (*f)();
};
B *b;
A()
{
b = new B(this->a);
}
int a()
{
}
};
int main()
{
A a;
}
compilation error:
If you absolutely need to call a function by pointer you will need to use a pointer to member function instead of a pointer to function. A pointer to member function has a different declaration syntax that includes the class type the function belongs to. In your case the parameter declaration would look like int (A::*cp)(). You will also need to change the declaration of the f member variable to int (A::*f)().
In order to call a pointer to member function you need to have a pointer to an object of the type the function belongs to. You also need to use one of the pointer to member operators; ->* or .*
void call(A* c, int (A::*f)())
{
(c->*f)(); // call member function through pointer
}
The extra set of parenthesis is required due to the order of precedence of operators.
The following code includes the changes necessary for you to use pointer to member functions.
class A
{
public:
class B
{
public:
// Take a pointer to member function.
B(int(A::*cf)())
{
f = cf;
}
void call(A* c)
{
(c->*f)();
}
int (A::*f)(); // pointer to member function
};
B *b;
A()
{
b = new B(&A::a);
}
int a()
{
return 0;
}
};
int main()
{
A a;
a.b->call(&a);
}
I also recommend that you consider using std::function and std::bind (or their Boost equivalents if you do not have a C++11 compiler).
Do not use function pointers in the first place when using C++.
There is an easier and more elagant solution - an interface.
i.e.
class Interface {
public:
virtual int CallMe() = 0;
};
class B : public Interface { int CallMe() { return 5; };
class A : public Interface {
private:
Interface *m_i = 0;
public:
A(Interface *i) : m_i(i) { }
A() : m_i(this) { };
void DoIt() { cout << m_i->CallMe() << endl; }
int CallMe() { return 8; }
};
int main() {
A a(new B); // Coult be any object that implements Interface (as yes it is a memory leak
A aa();
a.DoIt(); // Will print 5
aa.DoIt(); // WIll print 8
return 0;
}
I am having a design problem in my program because I need to occasionally access properties & methods of subclasses that are all stored in a vector of base class pointers. My code looks something like this:
class B1;
class B2;
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual B1 *getB1() { return NULL; } //seems like a bad idea
virtual B2 *getB2() { return NULL; } //to have these two functions
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getX() { return x; }
B1 *getB1() { return this; }
};
class B2 : public Base {
private:
int y;
public:
int getY() { return y; }
B2 *getB2() { return this; }
};
class Thing {
private:
std::vector<Base*> bases;
void addBase(Base *base) { bases.push_back(base); }
void doB1Stuff();
void doB2Stuff();
void setAandB(int ID, int newA, int newB); //set a and b of one of the elements in bases vector based upon the id given
};
The problem is if I need to access x or y in Thing, like this below:
void Thing::doB1Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
if (it->getB1()) {
//do stuff with b1
}
}
}
The code above should work, but if it seems a bad idea because one could easily forget to check if the pointer is null before using B1/B2 properties like this:
void Thing::doB2Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
std::cout << it->getY(); //I believe this will crash the program if a NULL pointer is returned
}
}
My question thus is: what is a good way of accessing subclass properties? I was thinking of having two separate vectors for B1s and B2s in Thing, but that doesn't seem like a good idea either because I need to be able to set a and b easily. Any thoughts?
What you have is perfectly fine: as long as you do not store NULLs in the bases vector of pointers, there is no need to null-check the values returned from the iterator. Unfortunately, a vector of pointers is your only option for containers of polymorphic objects. You can make a vector of shared pointers to simplify dealing with deletions, but the basic idea would remain the same.
You can check whether the item you are accessing is the right subclass type you are looking for although to do this you need run time type information (rtti) included.
Then if it is of a certain type and not null you can cast it to that type and call the correct function.
Also you can use dynamic_cast although for this to work you need rtti again and it is essentially the same as checking yourself and then static casting.
You're right that's not a great way of approaching the problem, you can use dynamic_cast to have a safe way to determine which object to use, but that is bad code smell to me.
What I would do instead to access sub properties is create a virtual function that returns the value you want in the Base class.
Example:
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual int getSubValue() = 0; //
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getSubValue() { return x; }
};
class B2 : public Base {
private:
int y;
public:
int getSubValue() { return y; }
};
Then you can just call it->getSubValue() to get the sub value you request.
This is my opinion and there are many ways to handle this, but this is what I would suggest based on the information you've given.
#include<iostream>
using namespace std;
class Abs
{
public:
virtual void hi()=0;
};
class B:public Abs
{
public:
void hi() {cout<<"B Hi"<<endl;}
void bye() {cout<<"B Bye"<<endl;}
};
class C:public Abs
{
public:
void hi() {cout<<"C Hi"<<endl;}
void sayonara() {cout<<"C Sayonara"<<endl;}
};
int main()
{
Abs *bb=new B;
bb->bye();
Abs *cc=new C;
cc->sayonara();
}//main
The compiler says
test2.cpp: In function ‘int main()’:
test2.cpp:26: error: ‘class Abs’ has no member named ‘bye’
test2.cpp:28: error: ‘class Abs’ has no member named ‘sayonara’
Because of this problem, I'll have to add functions to the Abs class each time I create a new derived class which inherits from it (Upcasting is compulsory for me to do. The program I'm planning requires it to be so). I don't want to touch the base class once it's created.
Doesn't this problem violate the principle that once you make a base class, you won't have to modify it ever. Any way to resolve this problem?
p.s: I've seen the factory design pattern and the prototype design patterns, but both of them can't seem to be able to solve it.
This is defeating the purpose of inheritance and abstract interfaces. bye and sayonara both do the same thing (saying goodbye), only in different languages. This means you should have an abstract say_goodbye method that gets overridden for subclasses. I suppose this is a simplified example, so maybe you could describe your actual scenario so we can provide more specific help.
Edit If you want to create a copy of the derived class through an abstract interface, check out this question. If you want to explicitly access the different attributes of your subclasses, you should be asking your self if subclassing es even appropriate here, since your classes don't seem to have much in common.
Well, i'm not sure to understand exactly what you want (and why you want it that way) but:
int main()
{
Abs *bb=new B;
static_cast<B*>(bb)->bye();
Abs *cc=new C;
static_cast<C*>(cc)->sayonara();
}//main
Will work.
You just have to be sure that bb is really a B* before you static_cast.
You may also use dynamic_cast which will return a null pointer if bb is not of the correct type.
int main()
{
B *bb = new B;
bb->bye();
C *cc=new C;
cc->sayonara();
}//main
This way modifications in the base class are no longer needed :)
Dynamic casting is a sensible option. If you're religious about dynamic casts, you can use the visitor design pattern:
struct Abs;
struct B;
struct C;
struct Visitor
{
virtual ~Visitor() {}
// Provide sensible default actions
virtual void visit(Abs&) const { throw "not implemented"; }
virtual void visit(B& b) const { visit(static_cast<Abs&>(b)); }
virtual void visit(C& c) const { visit(static_cast<Abs&>(c)); }
};
struct Abs
{
virtual ~Abs() {}
virtual void hi() = 0;
virtual void accept(Visitor const& v) { v.visit(*this); }
};
struct B : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void bye() { ... }
};
struct C : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void sayonara() { ... }
};
struct DoSayonara : Visitor
{
void visit(C& c) const { c.sayonara(); }
};
struct DoBye : Visitor
{
void visit(B& b) const { b.bye(); }
};
struct ByeOrSayonara : Visitor
{
void visit(B& b) const { b.bye(); }
void visit(C& c) const { c.sayonara(); }
};
and then you use
Abs* b = new B(); Abs* c = new C();
b->accept(DoSayonara()); // Throw an exception
c->accept(DoSayonara()); // Do what is expected
Do this only when you really need it.
If upcasting is compulsory and you need to call methods defined in the subclasses then You're Doing It Wrong.
However, at a given point in time, you either know that an object is a specific subclass, in which case you can dynamically cast to that type, or you don't and can't be sure you can call the function.
Assuming this is related to your other question, I've tried to explain a way to implement that particular problem in a different manner there.