I am a newbie in C++.
Can anyone tell me why the following source code runs well?
#include <iostream>
using namespace std;
class A{
public:
A(){ cout << "create a" << endl; }
void sayGoodbye() { cout << "goodbye" << endl; }
};
class B{
public:
B() { cout << "create b" << endl; }
void sayHello() { cout << "hello" << endl; }
};
int main(array<System::String ^> ^args)
{
A* a = new A();
((B*)a)->sayHello();
a->sayGoodbye();
return 0;
}
Output:
create a
hello
goodbye
What I wonder is why can the a access B::sayHello just by casting like that?
Can it access every public members of any class by that way?
Yes, you can.
But, no, you can't.
When you use a C-style cast like that, you are promising to the computer that you know what you're doing, and that the cast is valid. When it is valid, you're fine. When it's not, it's your fault.
In this case, it's not, and it's your fault.
Now, you can ask why it "runs well", but that's incidental: that's pure chance. Once the program is compiled, it's only going to crash or murder your step-children if you literally access invalid memory. In this particular case, you're not accessing invalid memory.
Doesn't mean you're right, though.
Don't do this.
This is not an answer to your question, however it can give you more knowledge and options when working with pointer casting:
You can see several casting techniques as follows:
static_cast
dynamic_cast
const_cast
reinterpret_cast
C-style cast (type)value
Function-style cast type(value)
In my case, I use dynamic_cast to check this casting problem. And it also helpful in case of down-casting.
But have one problem with dynamic_cast in down-casting is that we must have polymorphic class type.
Since the functions you defined for classes A and B don't depend on any data stored in those classes, the computer doesn't have to read anything to run the functions and they are able to execute.
In general, though, if the the sayHello method needed to read data stored on the B class, your cast would result in a seg fault or some other serious problem, since that would make the computer read into memory it is being told is allotted to fit an object of type B, which is not the case since the object is of type A.
sayHello method is not accessing any data member from class B. Also, ((B*)a)->sayHello(); is compiled to something like call-to-mangled-sayHello-member-function-of-B(this) . So, class B member function sayHello will be invoked by passing a pointer to an object of B and that pointer is not being used within the sayHello method. So, it will work in this case.
((B*)0)->sayHello();
((B*)1)->sayHello();
((B*)2)->sayHello();
In fact all the above calls will work. sayHello will receive a this pointer with address 0, 1, 2. As sayHello is not accessing any data member of B, so they will work. If sayHello access any non-static data members, then there will be a big crash. Generally, behavior is undefined.
If sayHello is virtual, then there will be real problems. Because, in that case a valid object in memory will be needed to resolve the called function at runtime.
Related
#include<iostream>
using namespace std;
class Class1 {
public:
virtual void f() {
cout << "Function f() in Class1\n";
}
};
class Class2 {
public:
virtual void h() {
cout << "Function h() in Class2\n";
}
};
int main() {
Class1 object1, *p;
Class2 object2;
p = &object1;
p = (Class1*)&object2;
p->f();//possibly abnormal program termination. but in fact, it will call function h(),Why?
return 0;
}
The code must be wrong in theory because p->f() there is no function f() in the Class2.
But in fact, the code can be run, and it will call Function h() in the Class2, It's so strange,why??
C++ doesn't have many run-time checks for performance reasons, so it will just do what you tell it to do even if it is illogical.
You are telling it to call the virtual method Class1::f on a pointer organised in the memory layout of Class2 and apparently Class2::h aligns with Class1::f so it gets called.
This is not standardised behaviour and may differ between compilers. See Virtual method table.
There is a problem with the code, and as #tkausi commented, the behavior is undefined.
The problem is that you are using C-style cast which is dangerous and should be avoided in C++. From cppreference:
When the C-style cast expression is encountered, the compiler
attempts to interpret it as the following cast expressions, in this
order:
const_cast<new_type>(expression);
static_cast<new_type>(expression), with extensions: pointer 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). Same applies to casting pointer to
member to pointer to member of unambiguous non-virtual base;
static_cast (with extensions) followed by const_cast;
reinterpret_cast<new_type>(expression);
reinterpret_cast followed by const_cast.
The first choice that satisfies the requirements of
the respective cast operator is selected, even if it cannot be
compiled (see example). If the cast can be interpreted in more than
one way as static_cast followed by a const_cast, it cannot be
compiled. In addition, C-style cast notation is allowed to cast from,
to, and between pointers to incomplete class type. If both expression
and new_type are pointers to incomplete class types, it's unspecified
whether static_cast or reinterpret_cast gets selected.
Thus, in your case the compiler will select reinterpret_cast which will just reinterpret the raw bytes of your object as something else (and it just happens that the first thing in the virtual table of p points to method h).
To make your program safe, you should instead use static_cast or dynamic_cast:
#include<iostream>
using namespace std;
class Class1 {
public:
virtual void f() {
cout << "Function f() in Class1\n";
}
};
class Class2 {
public:
virtual void h() {
cout << "Function h() in Class2\n";
}
};
int main() {
Class1 object1, *p;
Class2 object2;
p = &object1;
p = static_cast<Class1*>(&object2); // fails to compile
p->f();
return 0;
}
In this case, compilation fails as expected.
Live example: https://godbolt.org/g/noErNr
Note that if we replace static_cast line with p = dynamic_cast<Class1*>(&object2); the code will compile, but p will be set to nullptr at runtime, and trying to call p->f() will result in an error.
The code must be wrong in theory because p->f() there is no function
f() in the Class2.
The code is not only wrong in theory, but it is wrong in pratice too. The thing is that C++ does not hold your hand and does not wrap you in cotton wool, if you do wrong stuff, bad things can happen. Typesafety is your friend, but if you betray it, you are on your own.
In this line:
p = (Class1*)&object2;
you pretend that you could cast a Class2 to a Class1. Anything beyond that is undefined behaviour, which is sloopy speaking a way of saying: c++ does not care what is the output of programs that dont obey the rules.
The way to stay friends with the typesystem is to use static_cast instead of a C-style cast, which would tell you that the cast is not allowed.
I have a cpp code where in class c is derived from class b and class b is derived from class a.
Now class b has some public data member. So I am creating a instance of class c on heap passing its pointer to another class as pointer to a and there it is downcasting that pointer to pointer of class b and then printing public variables of class b.
Is this a valid downcasting. I am asking because just change of compiler has broken this working code.
I am including below code snippet which captures problem I am having.
#include <iostream>
using namespace std;
class grand
{
};
class parent : public grand
{
public : parent(){i=0;}
int i;
parent(int j){ i = j;}
void set(int j){i = j;}
};
class child : public parent{
public: child(){};
};
void print ( grand* ptr)
{
parent *p = (parent*) ptr;
std::cout << std::endl << p->i << std::endl;
}
int main() {
// your code goes here
child c;
c.set(9);
print(&c);
return 0;
}
Thanks
Is this a valid downcasting.
Yes. Your cast internally applies static_cast, which, according to §5.2.9/11, will give you the right result. If the argument for ptr doesn't point to a parent, the result of the cast is undefined - and so would the execution of the following code be.
Downcasting of polymorphic types in C++ works via dynamic_cast. Your grand class above isn't polymorphic - you have to add at least a virtual destructor to grand to make it polymorphic. Otherwise you'll get a compiler error with the following code.
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
And check whether the result, p, is non-zero. Only this method reveals (at runtime) whether the cast worked! All others either invoke undefined behavior or undefined, non-zero values.
Some notes:
Downcasting is almost always a sign of bad design. Avoid it if possible, using - for example - virtual (print) functions.
print should take a pointer to const since it doesn't modify any data members.
Your code, as written, is in fact valid, but there are a bunch of observations I'd like to make. Note that it's valid only because the object you pass to print is a parent or further derived class.
Then note that since you have to cast it the print function it's much safer to just change the function signature to take aparent instead of a grand and then you don't have to worry about the casting.
Then note that a likely cause of your problem is that in the file that does the cast, the compiler doesn't see the relationship between grand and parent so your C-style cast falls back to reinterpret_cast which is not what you want. If you can't change the signature of print at least change the cast to static_cast (or possibly dynamic_cast, but you can't do that in your example because the classes aren't polymorphic) so that the compiler will fail to compile when it can't see the class relationship.
Instead of a C-style cast you should apply a dynamic_cast or a at least a static_cast if you compile without RTTI (runtime type information) for some reason.
Your C-style cast is the same as a reinterpret_cast, which essentially interprets the memory pointed to as if an object of type parent would have been constructed there. But, every compiler may have a different memory layout of derived classes, thus that may work in some circumstances but there's no guarantee.
Can i safely call virtual functions after using static_cast on polymorphic class in situations like in the following code or is it UB?
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
virtual void foo() { std::cout << "Derived::foo() \n"; }
};
int main()
{
Base* derived = new Derived;
Derived* _1 = static_cast<Derived*>(derived);
_1->foo();
}
Yes, you can. Although I don't see the point of doing that in your specific example. Just calling it as
derived->foo();
without any casts would have produced exactly the same effect. I.e. some sort of static_cast in that case would be performed implicitly by the virtual call mechanism.
Note that your static_cast does not in any way suppress the "virtual" nature of the call.
That actually makes me wonder what your question is really about. Why would you even ask about it? What are you trying to do? In your code sample really representative of what you are trying to do?
If the compiler allows you to static_cast and at run-time the dynamic type of the object is as expected, then yes, you can. The question is why do you want to do that...
Yes, but as others have said, you don't need to cast the pointer to the derived type to call virtual functions.
However, it is usually safer to use dynamic_cast when dealing with inherited classes. Using dynamic_cast will generate the proper errors if the type information is incorrect at runtime.
Derived* d = dynamic_cast<Derived*>(derived); //safer, but still unnecessary in this situation
As written, that's going to work, basically because derived is a Derived*. So, all the cast is doing is telling the compiler what you already know. Then again, even without the static cast, you'll just end up with Derived::foo in your output. So, this is somewhat pointless. Still, you might need to do this in a situation where you're absolutely sure you know the actual instanced type of your variable and you need to access some non-virtual members for some reason. If you're using a badly designed class library, for instance...
But, in general, static downcasts are a bad idea. You might end up trying to downcast a variable that isn't a Derived*, in which case, calling virtual (or non-virtual) functions (or, in fact, using that pointer for almost any non-trivial operation) results in Undefined Behavior.
I've wrote a piece of code, but I am confused with its output:
#include <iostream>
using namespace std;
class B{
public:
virtual void foo() {cout << "B::foo" << endl;}
};
class D:public B{
public:
virtual void foo() {cout << "D::foo" << endl;}
void disp() {cout << "D::disp" << endl;}
};
void func(B *pb){
D *pd1 = static_cast<D*>(pb);
pd1->foo();
pd1->disp();
}
int main(int argc, char *argv[])
{
B* pb = new B();
func(pb);
return 0;
}
The output is:
B::foo
D::disp
But as far as I know, pb points to type B. And there's no function named disp() in it? So, why could it get access to disp() function in class D?
Since disp() doesn't access any of the members of the class, it is in principle the same as if it were declared in the global namespace instead of in class, so there are no negative side effects to calling it, even though the instance is not of the right class.
What are you doing is downcasting a pointer of a base class to a pointer of the derived class, even though it was not initialized as such. If disp() tried to access class members that were in D but not in B, you would probably run into segfaults.
Bottom line: don't use static_cast for downcasting unless you're absolutely sure the pointer is actually pointing to an instance of the derived class. If you're unsure, you can use dynamic_cast which fails in the event of mismatch (but there is the overhead of RTTI, so avoid it if you can).
dynamic_cast will return nullptr if the cast is incorrect or throw a std::bad_cast
exception if it casts references, so you will know for sure why it fails instead of possible memory corruption bugs.
The line:
D *pd1 = static_cast<D*>(pb);
Will make the cast regardless if the source pointer is B* or D*. In your case the result will be pointer that points to an object of a wrong type. Method disp will work because it is not using any data member or virtual function of the class D. In more complex case this will lead to unstable behaviour or a crash.
Your objects are polimorphic. You should use the dynamic_cast instead.
What's important in this context, I believe, is that the member function disp() isn't tucked away inside all objects of type D. It's a single function that exists in one place. And whether any object will try to call call disp() is decided by the code.
Your static_cast will produce what the compiler considers a pointer to D regardless of what pointer you pass it. And once you have a pointer to D, the compiler will let you attempt to call disp().
Put another way, static_cast will not protect you from casting a pointer incorrectly.
You did something very bad when you cast a pointer to an object allocated as a B to a pointer to a derived class D. Here's what the standard says, emphasis mine:
5.2.9 Static Cast
If the rvalue of type “pointer to cv1 B” points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
You've invoked undefined behavior by doing that static_cast. The compiler and runtime can do anything and still be compliant when the program invokes undefined behavior.
You need to understand the difference between the various types of C++ casts.
You're using a static cast here, which is the same as saying, "I don't really care if it's actually of that type or not - just try your best".
In this case, you want to know if your pointer is actually of the derived type you're casting it to. You should use a dynamic_cast. This cast will succeed only if the pointer is of the correct type. That means, that if it fails, it will return a NULL pointer.
The behavior you're seeing is what happens when you don't use the right cast for the job, which, while you can try to explain it, is something you really should avoid because it falls in the domain of undefined behavior. In other words, you cannot expect the same side effects across compilers or even different versions of the same compiler. In other words, avoid it.
I have been studying c++ for an exam and I thought that i had understood most of the c++ commons misconcemptions with much fatigue but i've encountered an exercise from a past exam that is driving me crazy, it combines virtual methods and inheritance in a way that i dont seem to understand here is the code:
#include <iostream>
class B;
class A {
public:
virtual A* set(A* a) = 0;
};
class B : public A {
public:
virtual A* set(B* b) {
std::cout << "set1 has been called" << std::endl;
b = this;
return b;
}
virtual B* set(A* a) {
std::cout << "set2 has been called" << std::endl;
a = this;
return this;
}
};
int main(int argc, char *argv[]) {
B *b = new B();
A *a = b->set(b);
a = b->set(a);
a = a->set(b);
a = a->set(a);
return 0;
}
the output is
set1 has been called
set2 has been called
set2 has been called
set2 has been called
From what i've gathered the first call (b->set(b) ) calls the first method of class B and return b itself and then this objectref gets casted to A meaning that now the object b is now of type A?
so i have A *a = A *b;
now it makes sense to me that i should call set of A since i have this situation in my mind
objectoftypeA->set(objectoftypeA) so i m not supposed to look into virtual methods since the two object are base classes ?
Anyway as you can see I have much confusion so bear with me if i make stupid errors i would be glad if someone could explain whats going on this code,i tried to search the web but i find only small and easy example that dont cause troubles.
The program demonstrates how member functions are looked up. The static type of the object determines the function overload that will be called: it performs the name lookup. The dynamic type then determines the virtual override that gets called.
Perhaps the key point is that different overlods of the same name are really different functions.
Since A has only one set member, there is only one thing that can happen when you call a->set(), no matter what the argument is. But when you call b->set(), there are a couple potential functions, and the best one is selected.
Since B::set is never overridden, it makes no difference whether it's virtual or not. virtual members of the same class don't talk to each other at all.
Potatoswatter is right, but I think I have a bit "clearer" explanation. I think the OP is getting confused on what happens at run-time with dynamic type lookup versus compile-time, and when up-casting happens automatically, versus when it does not.
First off, return type does NOT affect which overload is called. You probably know that, but it bears repeating. A return type mis-match will cause an error at compile-time, but not run-time, and does not affect which overload is called. Also it's worth noting that as long as it is a compatible pointer type (in a hierarchy together) returning a pointer doesn't ever "change" it. It is still the same pointer, unlike converting floats to ints, where there is an actual change.
Now to go through the calls one-by-one. This is my understanding of the process, not necessarily what the standard, or what "really" happens.
When you call b->set(b) the compiler (not run-time) goes "looking for a method named set with an argument of pointer to B" which it finds with the one that outputs set1. It's virtual, so there's code to check if the class points to anything lower, but there isn't, so it just calls it, and returns the this pointer into a.
Now you're calling b->set(a). Again it's the compiler that goes "does b have an overload that takes pointer to A?" Yes it does, so it calls the "set2" method. It's the compiler that sees an A* and so the call is "determined" at that point. Even though the pointer points to an object that is of type B, the compiler doesn't know that, or care. So it's the compile-time types of the arguments that determine which overloaded method get taken. From that point on, where in the hierarchy the virtual gets taken is on the underlying type of the this pointer, but only downward.
Here's a different case though. Try this: b->set(dynamic_cast<B*>(a)) This should call the "set1" method, because the compiler is going to definitely have a pointer to B (even if it's nullptr).
Now the third case: a->set(b). What's happening here is the compiler says "there is only one set method, so can the argument be up-cast or constructed to that type?" The answer is yes, as B is a child of A. So that cast happens transparantly, and the compiler calls the ABSTRACT dispatcher for the set method of the type A. This occurs at compile time before the "real" type of what a is pointer to. Then at run-time, the program "walks the virtual" and finds the lowest one, the B->set(A*) method that emits "set2". The actual type of what the argument points to isn't used, only the type to the left of the arrow operator, and that only determines how far down the hierarchy.
And the fourth case is just the 3rd again. The type of the argument (the pointer, not whta is pointed to) is compatible, so it goes as before. If you want a dramatic demonstration of this, try this:
a->set((A*)nullptr) // prints "set2 has been called"
b->set((A*)nullptr) // prints "set2 has been called"
b->set((B*)nullptr) // prints "set1 has been called"
The underlying type of what the arguments point to doesn't affect dynamic dispatch. Only their "surface" type affects the overload called.