About multiple inheritance and ambiguity - c++

In the following example:
class A {
public:
virtual void f() { cout << "a" << endl; }
virtual void h() { cout << "A" << endl; }
};
class s1 : public A {
public:
virtual void f() { cout << "s1" << endl; }
};
class s2 : public A {
public:
virtual void h() { cout << "s2" << endl; }
};
class GS : public s1, public s2 {
public:
};
int main()
{
s1 *q = new GS;
q->h();//no problem
GS a;
a.h();//error
}
Why does a.h(); give an ambiguity error yet q->h(); doesn't?
Doesn't *q have an instance of GS which should cause the same ambiguity problem?

Your use of multiple inheritance causes two instances of A to appear in GS. When you use S1 *q to access the GS instance, it follows the A instance associated with S1. Since S1 does not implement h(), the output of q->h() will be the implementation provided by A itself.
If you want q->h() to use the implementation provided by S2, then you need to create a diamond using virtual inheritance. Doing so will also remove the ambiguity when using a.h(), since virtual inheritance will cause only one instance of A to appear in GS.
class s1 : virtual public A {
public:
virtual void f() { cout << "s1" << endl; }
};
class s2 : virtual public A {
public:
virtual void h() { cout << "s2" << endl; }
};

Name lookup is based on static type not dynamic type. (And it has to be, since it occurs at compile time not run time.)

Because your pointer is of type s1 so the compiler knows to call h() (inherited from class A). Try using a pointer of type GS and you'll get an error for the pointer too. In the case of GS you are inheriting from s1 and s2, both classes inherit from A and thus, multiple(2) definitions of h() are found which is ambigious. This is the dreaded diamond.

Ok, this is because when the compiler evaluates q->h(), q only has one function named 'h' in its scope since it is of type s1.
When the compiler evaluates a.h(), a has two functions named 'h' in its scope. The one from s1 and the one from s2.
The compiler doesn't know which one you wanted to use, so it throws an error.

*q doesn't give an ambiguity error because its type is s1*. This means that the compiler will call s1::h, which is unambiguous.

Related

How to use inheritance to form a generic callback function pointer?

I am trying to write a function that would take in a generic function pointer as an argument.
Suppose you have a class A and its derivatives like below
class A {
};
class A1: public A {
};
class A2: public A {
};
class A3: public A {
};
I have another function
void registerCallback(std::function<void(A*)> func_ptr) {
}
int main() {
std::function<void(A1*)> fptr= [&](A1*) {
cout << "dummy" <<endl;
};
registerCallback(fptr); /// throws error
}
It tells you, cannot convert std::function<void(A*)> to std::function<void(A1*)>
How can I solve this problem?
How can I solve this problem?
You can use A* instead of A1* in the definition of fptr.
std::function<void(A*)> fptr= [&](A*) {
cout << "dummy" <<endl;
};
It is instructive to understand why your code is erroneous, not just from a syntactic point of view but also from a semantic point of view.
From a syntactic point of view, A1* can be used where A* where is expected -- it is an automatic pointer conversion. However, std::function<void(A1*)> cannot be used where std::function<void(A*)> is expected. There is no automatic conversion.
It's more important to understand the semantic problem if that was not
a syntactic error. Let's say for the sake of this discussion that the language/compiler accepted your code. Let's take the code a bit further. Update your code to the following:
class A {
};
class A1: public A {
public:
int int_var;
};
class A2: public A {
public:
double double_var;
};
class A3: public A {
public:
std::string string_var;
};
static std::function<void(A*)> registered_function_ptr;
void registerCallback(std::function<void(A*)> func_ptr) {
registered_function_ptr = fun_ptr;
}
void callRegisteredFunction(A* a_ptr) {
registered_function_ptr(a_ptr);
}
int main() {
std::function<void(A1*)> fptr= [&](A1* a1_ptr) {
// Expecting a pointer to an A1 object.
// Should be able to use members of A1.
cout << "int_var: " << a1_ptr->int_var << endl;
};
registerCallback(fptr);
A2 a2;
a2.double_var = 20;
// Syntactically correct.
callRegisteredFunction(&a2);
A3 a3;
a3.string_var = "Some string";
// Also syntactically correct.
callRegisteredFunction(&a3);
}
When callRegisteredFunction is executed, it calls the registered function. In this case it is fptr. fptr expects a pointer to an A1 object but we are able to call it indirectly with objects that are different -- they don't have int_var. Instead, they have double_var and string_var. That will definitely lead to undefined behavior. The compiler and the language are preventing you falling into that trap.
Just declare fptr as a callable object with parameter of basic type - std::function<void(A*)>. It will still accept all classes (publicly) derived from A:
int main() {
std::function<void(A*)> fptr= [&](A*) {
std::cout << "dummy" << std::endl;
};
A1 *a = new A1{};
fptr(a); // all good
}

Pointer to a Superclass object may serve as pointers to subclass objects. But can't call memeber functions of the subclass. why?

I am enrolled in a C++ course, where i have the following code snippet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound()
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet *a_pet1 = new Cat("Tom");
Pet *a_pet2 = new Dog("Spike");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
a_pet2 -> run();
// 'a_pet2 -> make_sound();' is not allowed here!
}
I'm not able to figure out why this is invalid. Please suggest suitable references for this that have ample explanation about why this is happening.
In C++, the types and names of variables at any point is what the compiler permits itself to know.
Each line of code is checked against the types and names of variables in the current scope.
When you have a pointer to a base class, the type of the variable remains pointer to the base class. The actual object it is pointing at could be a derived class, but the variable remains a pointer to the base class.
Pet *a_pet1 = new Cat("Tom");
a_pet1 -> run();
// 'a_pet1 -> make_sound();' is not allowed here!
the type of a_pet1 is Pet*. It may be pointing at an actual Cat object, but that is not information that the type of a_pet1 has.
On the next line, you are using a_pet1. You can only use it in ways that are valid for a Pet pointer on this line. a_pet1->make_sound() is not a valid operation on a Pet pointer, because the Pet type does not have a make_sound method.
You could do this:
Cat *a_pet1 = new Cat("Tom");
a_pet1 -> run();
a_pet1 -> make_sound(); // it now works!
because we changed the type of a_pet1 from Pet* to Cat*. Now the compiler permits itself to know that a_pet1 is a Cat, so calling Cat methods is allowed.
If you don't want to change the type of a_pet1 (which is a reasonable request), that means you want to support make_sound on a Pet, you have to add it to the type Pet:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void make_sound();
void run()
{
cout << name << ": I'm running" << endl;
}
};
now, a_pet1->make_sound() will be allowed. It will attempt to call Pet::make_sound, which is not Dog::make_sound, and as we didn't provide a definition for Pet::make_sound, this will result in an error at link time.
If you want Pet::make_sound to dispatch to its derived methods, you have to tell the compiler this is what you want. C++ will write the dispatch code for you if you use the virtual keyword properly, like this:
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
virtual void make_sound() = 0;
void run()
{
cout << name << ": I'm running" << endl;
}
};
here I both made make_sound virtual, and made it pure virtual. Making it virtual means that the compiler adds information to each Pet and Pet derived object so, when it is actually pointing to a derived object type and not a Pet, the caller can find the right derived method.
Pure virtual (the =0) simply tells the compiler that the base class method Pet::make_sound intentionally has no implementation, which also means that nobody is allowed to create a Pet, or a even Pet derived object instance, without providing a make_sound implementation for its actual type.
Finally, note that I mentioned "permits itself to know". The compiler limits what it knows at certain phases of compilation. Your statement that a_pet1 is a Pet* tells the compiler "I don't want you to assume this is a Cat, even though I put a Cat in there". At later stages of compilation, the compiler can remember that fact. Even at runtime, it is sometimes possible to determine the actual type of an object (using RTTI). The forgetting of the type of the object is both intentional and limited.
It turns out that "forced forgetting" is quite useful in a number of software engineering problems.
There are other languages where all method calls to all objects go through a dynamic dispatch system, and you never know if an object can accept a method call except by trying it at runtime. In such a language, calling make_sound on any object whatsoever would compile, and at runtime it would either fail or not depending on if the object actually has a make_sound method. C++ intentionally does not do this. There are ways to gain this capability, but they are relatively esoteric.
In your example a_pet1 and a_pet2 are pointers to objects of the 'Pet' class so your compiler only allows you to access functions that are actually available in that class. The 'Pet' class iteself does not contain a 'make_sound' function in this case. To fix this problem you can define a 'make_sound' function in the base class and mark it as 'virtual'. This will make a function call over a base pointer always invoke the execution of the according function in the inheriting class.
class Pet {
protected:
string name;
public:
Pet(string n)
{
name = n;
}
void run()
{
cout << name << ": I'm running" << endl;
}
virtual void make_sound() {}
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Woof! Woof!" << endl;
}
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) {};
void make_sound() override
{
cout << name << ": Meow! Meow!" << endl;
}
};
int main()
{
Pet* a_pet1 = new Cat("Tom");
Pet* a_pet2 = new Dog("Spike");
a_pet1->run();
a_pet1->make_sound();
a_pet2->run();
a_pet2->make_sound();
}

How safe and compiler-independent is this C++ code?

I have created a bit of code that is strange to me, but seems to do what I want. However, I am not sure of its platform independence or how safe it is, or if there is a much easier way to do what I want.
I was reading on the Curiously Recurring Template Program (on wikipedia), and there was sample code for a class counter that lets each derived class keep track of how many instances have been created by inheriting from a base with that functionality.
I had been looking for ways to have derived classes reference to a common object (by pointer) without having to add a static variable and define a virtual function for each new class I create. (I was planing on creating quite a few derived classes.) But, the derived classes, because they were created with templates, were considered different from the base so they could not be implicitly converted to a base pointer.
Dynamic_cast and static_cast didn't work, so I tried reinterpret_cast, for fun, to see what behavior that had. It ended up showing the static variable from the base class, which isn't what I wanted, but it reminded me of a previous experience I had with statics and virtual functions (long story). I wrote a virtual function in the base class, and the virtual function reported the correct variable for the derived classes, polymorphic-ally.
It works, at least according to codepad.org, but I'm still not sure of its platform consistency or the safety of reinterpret_cast in this case. Can someone with more experience than I clarify exactly why this works?
Here is my code. It looks like the Wikipedia sample code because that's what it was originally.
#include <iostream>
using namespace std;
template <typename T>
class counter
{
public:
static int separateObject;
virtual void printStatic(){
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
typedef counter<void*>* voidcounter;
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
voidcounter polycount = reinterpret_cast<voidcounter>(counterX);
polycount->printStatic();
polycount = reinterpret_cast<voidcounter>(counterY);
polycount->printStatic();
return 0;
}
I had been looking for ways to have derived classes reference to a common object
Then don't use CRTP. CRTP is for when you need all of the base types to NOT be common (which is what allows each type to have it's own counter). That's 100% exactly what it's for. If you want a shared common base, use a normal virtual base class. You can't use static_cast or dynamic_cast because they have no base in common. What you're doing with reinterpret_cast is incredibly unsafe, as it is undefined behavior.
class shared_counter_base {
virtual ~shared_counter_base(){}
virtual void printStatic()=0;
};
template <typename T>
class counter : shared_counter_base
{
public:
static int separateObject;
virtual void printStatic() {
cout << this->separateObject << endl;
}
};
template <typename T> int counter<T>::separateObject( 0 );
class X : public counter<X>
{
// ...
};
class Y : public counter<Y>
{
// ...
};
int main(){
X* counterX = new X;
Y* counterY = new Y;
counterX->separateObject = 9001;
counterY->separateObject = 42;
cout << "Object Xs value is: " << counterX->separateObject << endl;
cout << "Object Ys value is: " << counterY->separateObject << endl;
shared_counter_base polycount = counterX;
polycount->printStatic();
polycount = counterY;
polycount->printStatic();
return 0;
}

Code executes derived class method, but gets default parameter from base class method

Can someone explain why the result of the code below would be "class B::1" ?
Why does the virtual method of derived class uses the default parameter of a base class and not his own? For me this is pretty strange. Thanks in advance!
Code:
#include <iostream>
using namespace std;
class A
{
public:
virtual void func(int a = 1)
{
cout << "class A::" << a;
}
};
class B : public A
{
public:
virtual void func(int a = 2)
{
cout << "class B::" << a;
}
};
int main()
{
A * a = new B;
a->func();
return 0;
}
Because default arguments are resolved according to the static type of this (ie, the type of the variable itself, like A& in A& a;).
Modifying your example slightly:
#include <iostream>
class A
{
public:
virtual void func(int a = 1)
{
std::cout << "class A::" << a << "\n";
}
};
class B : public A
{
public:
virtual void func(int a = 2)
{
std::cout << "class B::" << a << "\n";
}
};
void func(A& a) { a.func(); }
int main()
{
B b;
func(b);
b.func();
return 0;
}
We observe the following output:
class B::1
class B::2
In action at ideone.
It is not recommended that a virtual function change the default value for this reason. Unfortunately I don't know any compiler that warns on this construct.
The technical explication is that there are two ways of dealing with default argument:
create a new function to act as trampoline: void A::func() { func(1); }
add-in the missing argument at the call site a.func() => a.func(/*magic*/1)
If it were the former (and assuming that the A::func was declared virtual as well), then it would work like you expect. However the latter form was elected, either because issues with virtual were not foreseen at the time or because they were deemed inconsequential in face of the benefits (if any...).
Because default value is substituted during compilation and is taken from declaration, while real function to be called (A::func or B::func) is determined at runtime.
Because polymorphism in C++ takes effect at run-time, whereas the substitution of default parameters takes effect at compile-time. At compile time, the compiler does not know (and is not supposed to know) the dynamic type of the object to which the pointer a points. Hence, it takes the default argument for the only type it knows for a, which in your example is A *.
(This incidentally is also the reason default parameters are given in interfaces/headers rather than in implementations/definitions. The compiler never inserts the default parameter in the implementation's machine code, but only in the caller's machine code. Technically, the default parameter is the property of the caller; and the caller doesn't know -- and shouldn't need to know -- an object's dynamic type.)

How can I determine if a compiler uses early or late binding on a virtual function?

I have the following code:
class Pet {
public:
virtual string speak() const { return ""; }
};
class Dog : public Pet {
public:
string speak() const { return "Bark!"; }
};
int main() {
Dog ralph;
Pet* p1 = &ralph;
Pet& p2 = ralph;
Pet p3;
// Late binding for both:
cout << "p1->speak() = " << p1->speak() <<endl;
cout << "p2.speak() = " << p2.speak() << endl;
// Early binding (probably):
cout << "p3.speak() = " << p3.speak() << endl;
}
I have been asked to determine whether the compiler uses early or late binding for the final function call. I have searched online but have found nothing to help me. Can someone tell me how I would carry out this task?
You can look at the disassembly, to see whether it appears to be redirecting through a vtable.
The clue is whether it calls directly to the address of the function (early binding) or calls a computed address (late binding). The other possibility is that the function is inlined, which you can consider to be early binding.
Of course the standard doesn't dictate the implementation details, there may be other possibilities, but that covers "normal" implementations.
You can always use hack :D
//...
Pet p3;
memset(&p3, 0, sizeof(p3));
//...
If compiler does use vtbl pointer, guess what will gonna happen :>
p3.speak() // here
Look at the generated code. E.g. in Visual Studio you can set a breakpoint, then right-click and select "Go To Disassembly".
It uses early binding. You have an object of type P3. While it is a base class with a virtual function definition, the type is concrete and known at compile time, so it doesn't have to consider the virtual function mapping to derived classes.
This is much the same as if you called speak() in the Pet constructor - even when making derived objects, when the base class constructor is executing the type of the object is that of the base so the function would not use the v-table, it would call the base type's version.
Basically, early binding is compile time binding and late binding is run-time binding. Run time binding is only used in instances where the compiler doesn't have enough type information at compile time to resolve the call.
In fact the compiler has no obligation to use either one particularly, just to make sure that the right function is called. In this case, your object is of the concrete type Pet, so as long as Pet::speak is called the compiler is "doing the right thing".
Now, given that the compiler can statically see the type of the object, I suspect that most compilers will optimize away the virtual call but there is no requirement that they do so.
If you want to know what your particular compiler is doing the only way is to consult its documentation, source code, or the generated disassembly.
I just thought of a way to tell at runtime, without guesswork. You can simply override the vptr of your polymorphic classes with 0 and see if the method is called or if you get a segmentation fault. This is what I get for my example:
Concrete: Base
Concrete: Derived
Pointer: Base
Pointer: Derived
DELETING VPTR!
Concrete: Base
Concrete: Derived
Segmentation fault
Where Concrete: T means that calling the virtual member function of T through a concrete type was successful. Analogously, Pointer: T says that calling the member function of T through a Base pointer was successful.
For reference, this is my test program:
#include <iostream>
#include <string.h>
struct Base {
unsigned x;
Base() : x(0xEFBEADDEu) {
}
virtual void foo() const {
std::cout << "Base" << std::endl;
}
};
struct Derived : Base {
unsigned y;
Derived() : Base(), y(0xEFCDAB89u) {
}
void foo() const {
std::cout << "Derived" << std::endl;
}
};
template <typename T>
void dump(T* p) {
for (unsigned i = 0; i < sizeof(T); i++) {
std::cout << std::hex << (unsigned)(reinterpret_cast<unsigned char*>(p)[i]);
}
std::cout << std::endl;
}
void callfoo(Base* b) {
b->foo();
}
int main() {
Base b;
Derived d;
dump(&b);
dump(&d);
std::cout << "Concrete: ";
b.foo();
std::cout << "Concrete: ";
d.foo();
std::cout << "Pointer: ";
callfoo(&b);
std::cout << "Pointer: ";
callfoo(&d);
std::cout << "DELETING VPTR!" << std::endl;
memset(&b,0,6);
memset(&d,0,6);
std::cout << "Concrete: ";
b.foo();
std::cout << "Concrete: ";
d.foo();
std::cout << "Pointer: ";
callfoo(&b);
std::cout << "Pointer: ";
callfoo(&d);
return 0;
}