Let's say I have a base class 'A' and two classes 'B' and 'C', which are derived from the base class 'A'
I know I can do this
A *a = new B();
or
A *a = new C();
a->handle() //handle is a virtual function in A. class B and C overloaded this function and added its own implementation.
Then it will call the handle function from either B or C object.
But, I have a restriction that I cannot use a pointer in my program. I have to define A as
A a //not A *a
Then how do I implement this so that it calls the handle function from class B or C?
You can't. You cannot take a value of type A and pretend it's a B. That's just bad, and cannot be done.
Odd question. It can't. Not by any sane means. It's an 'A' afterall.
Assuming you know 'I want to call C's virt' you could do disturbing things like:
#include <stdio.h>
class A { public: virtual int foo() { return 1; } };
class B : public A{ public: virtual int foo() { return 2; } };
class C : public A{ public: virtual int foo() { return 3; } };
int main()
{
A a;
C *c = (C*)&a;
int x = c->C::foo(); // EXAMPLE 1
printf("x == %d\n", x);
x = ((C&)a).C::foo(); // EXAMPLE 2
printf("x == %d\n", x);
return 0;
}
Note that example 2 is just the same thing without anything in the middle. Harder to read, but same result.
The key is using C::foo(); Without C:: you will go through the virtual table and the result will be '1'.
If this is homework, then perhaps professor meant to use references (&) instead of pure pointers (*).
A &a = * new B();
or
A &a = * new C();
a.handle()
Though the references in C++ are pretty much the same thing as regular pointers.
Related
#include <iostream>
struct A {
virtual void a() {
puts("A");
}
};
struct B {
virtual void b() {
puts("B");
}
};
struct C {
virtual void c() {
puts("C");
}
};
struct D : public A, public B, public C {
virtual void c() {
C::c();
puts("cd");
}
};
int main() {
A* obj = new D;
obj->a();
B* b = (B*)obj;
b->b();
C* c = (C*)obj;
c->c();
return 0;
}
I have this code where I have non virtual multiple inheritance. However, it seems to call the wrong virtual function when I call the functions in the main function.
Instead of outputting:
A
B
C
cd
It outputs:
A
A
A
What puzzles me is that when I change the code to doing this:
B* b = (B*)(D*)obj;
b->b();
C* c = (C*)(D*)obj;
c->c();
It outputs what I would expect (see above). Afaik doing a double pointer cast like this wouldn't effect anything and would be optimized out by the compiler. But it seems to be changing what virtual function is being called.
Can someone explain why this would change what virtual function is being called?
Notes:
I printed the pointers at each step, they are the same.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
Can someone explain why this would change what virtual function is being called?
Generally, a C-style cast between pointer types won't change the value of the pointer and so will have no effect. There is, however, one exception.
A cast between a class and a parent or child class can change the value of the pointer. For example:
class A
{ int a; };
class B
{ int b; };
class C : public A, public B
...
Now, a pointer to an instance of class A will probably have the same value as a pointer to its a member and a pointer to an instance of class B will probably have the same value as a pointer to its b member. A pointer to an instance of class C can't have the same value as a pointer to both its A::a and its B::b members since they're distinct objects.
A function expecting a B* can be passed a C* since a C is a B. Similarly, a function expecting an A* can be passed a C* for the same reason. But at least one of these will require a value change to the pointer.
So casts between these types will change the values, the others are all no-ops.
Of course, all of this is UB. You are casting between unrelated types and then dereferencing them.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
That seems very hard to believe.
Here is the code
,it is my homework using overriden methods teacher told us to analyze the code. I know the code is outputting 2, I have no clue how this code work.
public:
int a;
virtual void who(void) { a = 1; }
};
class B:public A{
public:
int a;
void who(void) { a = 2; }
};
class C :public B {
};
int main(void) {
A x; B y; C z; A *p;
p = &z;
p->who();
cout << z.a << endl;
system("pause");
return 0;
}
B overrides the who() function of its parent, A. This is called polymorphism. C inherits from B, but doesn't override anything; thus, it uses all of the implementation of B.
p is a pointer to an object of class A. One of the key features of class inheritance is that a pointer to a derived class is type-compatible with a pointer to its base class [1].
This means that when you call a member function of a pointer (p->who()), and the class of the object the pointer is pointing to overrides a member of its parent, is going to use the overridden member.
Sources:
[1] http://www.cplusplus.com/doc/tutorial/polymorphism/
as long as you create a function with same input and output with name; in short: same function declaration.. the new one will be used as you refer to one which has super class that has same function. in your case; super class for C is B and it doesn't see A, but B sees A and use all functions it has except what's B declare a new implementation for.
I've a code as follows -
#include <iostream>
#include <string>
class A{
int a;
public: virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
int main() {
A *ptr = new B("c++");
ptr->sayHello();
return 0;
}
which produces the following compiler output -
Error:
prog.cpp: In function 'int main()':
prog.cpp:20:22: error: 'A' is an inaccessible base of 'B'
A *ptr = new B("c++");
^
As previously answered - here, here & here, I know how to solve this issue. By using public inheritence instead of private or protected.
But if I really really want to hide some interface behind the base class, isn't there some other way to do this? Or is it impossible to do so according to c++ lang specification.
If you want polymorphic pointer conversion to work outside the class, then the inheritance must be public. There is no way to work around that.
You could add a member function that does the polymorphic pointer conversion within the class:
class B : private A{
// ...
public:
A* getA() {
return this;
}
};
Which allows you to do this, while still allowing private inheritance:
B* b_ptr = new B("c++");
A* ptr = b_ptr->getA();
// ptr = b_ptr; // only allowed in member functions
I haven't encountered a real world design where this trick would be useful, but suit yourself.
PS. Remember that you should destroy objects that you create. Also do realize that delete ptr has undefined behaviour, unless ~A is virtual.
Even though I find it quite strange to hide the base class and want to cast B to A, you can use for that the operator A*().
It follows a minimal, working example:
#include <iostream>
#include <string>
class A{
int a;
public:
virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
operator A*() { return this; }
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
Now you can use it as:
int main() {
A *ptr = *(new B("c++"));
ptr->sayHello();
return 0;
}
Or even better:
int main() {
B b{"c++"};
A *ptr = b;
ptr->sayHello();
return 0;
}
Adding the cast to A& is as easy as adding the member method operator A&() defined as return *this;.
There is an unsightly way around this: C style casts. C style casts can cast to inaccessible base classes. This is the one and only case where C style casts can do something that C++ casts can't. From cppreference, when a C style cast (T) foo attempts to perform static_cast<T>(foo), it can do slightly more than just a static_cast:
[P]ointer or reference to a derived class is additionally allowed to be cast to pointer or reference to unambiguous base class (and vice versa) even if the base class is inaccessible (that is, this cast ignores the private inheritance specifier).
Emphasis added
Thus, you can do this:
int main() {
A *ptr = (A *) new B("c++");
ptr->sayHello();
return 0;
}
This is ugly, and it comes with all the disadvantages of casting and especially of C style casts. But it does work, and it is allowed.
Live on Wandbox
When you want to hide that A is a base of B this is valid.
But you assignment
A *ptr = new B("c++");
breaks this hiding, because you use an A*. So c++ generates an error because the dependency is hidden. You can do
B *ptr = new B("c++");
though.
Look at following code:
class A
{
protected:
int aa = 1;
};
class B : public A
{
private:
int bb = 2;
public:
int getbb() { return bb; }
};
class C : public A
{
private:
int cc = 3;
public:
int getcc() { return cc; }
};
int main()
{
std::vector<A> a;
B b;
C c;
a.push_back(b);
a.push_back(c);
a[0].getbb(); //getbb() unaccessible;
a[1].getcc(); //getcc() unaccessible;
}
A is the based class. B and C is the derived classes. I want to set a vector to hold either B or C, and use vector a to hold A. However, since a is a vector containing A's objects, I can't access methods in B and C. Is there anyway to make a[0].getbb() and a[1].getcc() work?
Your vector of A is not capable of holding Bs or Cs, because it stores A by value, resulting in object slicing when B or C is stored. In particular, this means that when you store B, only aa gets stored; bb gets sliced away.
In order to store subclasses without slicing use a container of pointers - preferably, of smart pointers.
This wouldn't help you access functionality specific to B or C without a cast. One way to solve this problem is to give virtual member functions for B's and C's functionality to A, and make calls through A-typed reference of B or C.
Not without invoking undefined behaviour.
The problem is that a.push_back(b) and a.push_back(c) do not append objects b and c to the vector. They create instances of A that hold only the "A parts". This is called object slicing.
So there is no object of type B and no object of type C in the vector.
You force the issue and make your code compile by doing something like
static_cast<B &>(a[0]).getbb();
but this just has undefined behaviour, since it treats a[0] as being of type B when it is really of type A. Which makes it a really bad idea. Although it will (probably) compile, it could do anything - and probably not what you expect.
If your vector contains A * rather than A it is possible. For example;
int main()
{
std::vector<A *> a;
a.push_back(new B);
a.push_back(new C);
B* b = dynamic_cast<B *>(a[0]);
if (b) // if a[0] actually points at a B ....
b->getbb();
else
complain_bitterly();
C *c = dynamic_cast<C *>(a[1]);
if (c)
c->getcc();
else
complain_bitterly();
}
Of course, doing this has practical trap doors as well - such as requiring class A having at least one virtual member. It would be better off to work with a polymorphic base, and override virtual functions.
In other words, your design is broken, so fix it so it doesn't somehow require you to morph an object to a different type.
An alternative to using pointers is to use a vector of std::reference_wrappers and polymorphic classes. Small example below:
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <vector>
class A
{
public:
virtual void printme()
{
std::cout << "A" << std::endl;
}
virtual ~A() = default;
};
class B: public A
{
public:
void printme() override
{
std::cout << "B" << std::endl;
}
};
class C: public A
{
public:
void printme() override
{
std::cout << "C" << std::endl;
}
};
int main()
{
std::vector<std::reference_wrapper<A>> a;
B b;
C c;
a.emplace_back(b);
a.emplace_back(c);
a[0].get().printme(); // need to "get()" the raw reference
a[1].get().printme();
}
Live on Coliru
According the the cpp reference, there seems to be a way to achieve this by using dynamic_cast. You first need to make your vector a vector of pointers to the base class A. Then when accessing any element, you can check if it is a B* (or a C*) by checking the result of the dynamic_cast operator.
From the CPP reference:
dynamic_cast < new_type > ( expression )
... If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type...
Accordingly, you can do this:
std::vector<A*> a;
B b;
C c;
a.push_back(&b);
a.push_back(&c);
...
int i = something;
B* pB = dynamic_cast<B*>(a[i]); if(pB != nullptr) pb->getbb();
C* pC = dynamic_cast<C*>(a[i]); if(pC != nullptr) pC->getcc();
p.s: It is highly questionable as design approach though. The recommended OOP approach would be certainly to use a virtual method in the base class A and override it in B and C. But (hopefully) this answers the exact question as stated in the title.
If you're sure they're instances of B and C, use cast:
static_cast<B>(a[0]).getbb();
static_cast<C>(a[1]).getcc();
OK, you may also create a vector of A*:
std::vector<A*> as;
as.push_back(new B);
as.push_back(new C);
B* b = (B*) as[0];
b->getbb();
c->getcc();
Now you only have to remember about freeing objects with delete.
You may use "Type IDs":
class A {
// ...
virtual int getTypeID() { return 0; }
}
class B {
// ...
virtual int getTypeID() { return 1; }
}
// analogically for C
It's virtual but is in prototype of A
Now use:
switch(a.getTypeID()) {
case 0:
// It's normal A
break;
case 1:
// It's B
// ...
break;
case 2:
// It's C
// ...
break;
}
I just cannot imaginate a way to do a call to a function with genericity. I have a code which a have to call a function in two different classes in different moments.
I have A and B classes which I can access one time or other time. Or I access A or I access B. Not both in the same type.
I have code this program but I just cannot imagine how to do this. Or if this is good for performance or codding. I just want to eliminate the C class but I don't know how.
Any idea?
class MyClass
{
public:
MyClass() {} //contructor padrão, não deve ser utilizado isoladamente
virtual int a() = 0;
virtual int b() = 0;
int c()
{
return b();
}
};
class A : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int d() { return 1; }
};
class B : public MyClass
{
public:
int a() { return 1; }
int b() { return 1; }
int e() { return 1; }
};
class C
{
public:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
C(TIPO tipo) { Tipo = tipo; }
int a()
{
switch(Tipo)
{
case A:
return ca.a();
break;
case B:
return cb.b();
break;
default:
break;
}
}
};
void main()
{
C c(C::B);
c.a();
return;
}
If I understand you correctly, you are trying to eliminate the members (ca,cb), and just call the appropriate base class method.
If that's the case, it can be done by using:
switch(Tipo) {
case A:
return A::a();
case B:
return B::a();
}
However, I would recommend revisiting your design. Typically, situations like this can often be handled by rethinking/reworking the class design so that there is a single base class or interface which defines a(), and instead of creating one concrete class with 2 base classes, create one of two specific, concrete classes derived from a single base class. There is no need for multiple inheritance here. (This is especially true since you know the type at construction time.)
As you've written 'A' and 'B', you don't actually need the C class. By declaring your member functions "virtual" you are using run time polymorphism and this will result in the "correct" functions being called:
void foo (MyClass & mc) {
mc.a ();
}
int main () {
A a;
B b;
foo (a); // 'mc.a()' will call 'A::a'
foo (b); // 'mc.a()' will call 'B::a'
}
Is there some other reason that you need to inherit from C?
First of all, decide if your A and B classes will belong to C by inheritance or by composition. Right now you're doing both, which is both bloating your code and making it confusing.
If you do go for inheritance, then you have another problem: similarly named overridden methods, a prime cause for the Deadly Diamond of Death. Multiple inheritance, in case you haven't heard, is evil. Avoid it unless there is no other way to get the job done.
If you go with composition (my recommendation), then it seems to me that your specification of "not at the same time" becomes unnecessary. You're not accessing the same data, so there's no possibility of a race condition. And if you are (for some ungodly reason) determined to access the same memory space, then you'll need to brush up on multithreading, the implementation of which will differ with each platform you develop on.
Ok, I guess you want C::a() to call A::a() or B::b() depending on what "type" or "mode" C has. First of all there is no need to let C inherit A and B.
class C
{
private:
A ca;
B cb;
enum TIPO { A, B };
TIPO Tipo;
public:
SetTipo(TIPO tipo) { Tipo = tipo; }
// ..
};
void main()
{
C c(C::B); // Start with mode B and call B::b()
c.a();
c.SetTipo(C::A); // Now I'm in mode A .. call A::a()
c.a();
return;
}
This assumes that C really should own one instance of A and one instance of B and I'm not sure if that's what you want. Your question didn't state if that's the case or not.
Cheers
This question is very unclear. I have another interpretation of the question, along with an answer.
Interpretation: given:
class C {
public:
int a();
int b();
};
You want to call either method a() or method b(), selectable at runtime. Solution: member function pointers.
A member function pointer is like a regular C function pointer, except that it applies to a method in a class, and its type signature includes the name of the class it's invoked on. Here's how to use one with the class I've just given:
typedef int (C::*SELECT_FUNC)(void);
This is the declaration of the member function pointer. It is similar to the declaration of a regular C function pointer, with the addition of a class name. Now we can assign it:
SELECT_FUNC ptr = &C::a;
SELECT_FUNC other_ptr = &C::b;
And to call:
C item;
C *item_ptr;
int rv = item.*ptr();
int rv2 = item_ptr->*other_ptr;
This syntax is funky. Think of the "*" as "dereference". We are dereferencing the member function pointer to get a METHOD, at which point we can invoke the method in what is otherwise the normal way.
The cool thing about this is: it doesn't even matter if the methods are virtual or not. You can assign either a virtual method or a non-virtual method to a member function pointer. If you call a method through a function pointer and the method happens to be virtual, then you'll get a true virtual call (i.e. if the function pointer is declared to point to a base class method, but you use a derived class instance for "this", then the derived class method will be called, just as it is for a normal virtual call.)
I would think through your requirements carefully. Your question is not well asked, which leads me to believe that you do not understand yourself what you really want to achieve. Once you understand what you want to achieve, then either a class hierarchy or member function pointers (or both) may be the best choice to solve your problem.