Why is a hidden function is using derived class variable? - c++

This is a very basic program but I thought it is necessary to get my doubt cleared.
The output of the below program is disp in base, x = 100.
In the below program, I am only setting the value of x in derived class object, which in turn is inheriting it from the base class. In base class x is being intialized with the value 10. What I failed to understand is that when I call the function disp using the syntax d1.base::disp() how does it takes the value of x from the derived class into the function of base class? I am expecting it to display 10 in place of x.
Is there some concept that I am missing here?
#include<iostream>
using namespace std;
class base {
public:
int x = 10;
void disp() {
cout<< "disp in base, x = " << x << endl;
}
};
class derived : public base {
public:
void disp() {
cout<< "disp in derived, x = " << x << endl;
}
};
int main() {
derived d1;
d1.x = 100;
d1.base::disp();
return 0;
}

Is there some concept that I am missing here?
Yes. Although your derived class disp() function hides the function with the same signature in the base class, it uses the same x member variable as the base class. This is the way inheritance works: functions and data that are not overridden (or hidden) by a derived class are inherited from the base class; internally, a derived object will have, as part of its memory layout, an actual base object, and the class will have access to the members of that base class, if the relevant access attribute (i.e. protected or public, but not private) is given to those members.
In your code, the derived class doesn't also hide/shadow that base class x member, so it uses the same variable. For the derived and base classes to have separate (i.e. different) x members, you would need to also declare that member in the derived class, like below:
class derived : public base {
public:
int x = 10; // Gives "derived" its own "x", which hides the base class member
void disp() {
cout << "disp in derived, x = " << x << endl;
}
};
With that modification, your d1.base::disp(); call will display the 10, which is the (unmodified) value of the base class member variable, because the d1.x = 100; line now modifies the entirely different x member of the derived class.
Note that hiding such data members is considered bad practice by many C++ programmers.

From what I can figure out if you were to add the following line in your main method,
d1.disp();
You will get the following output,
disp in base, x = 100
disp in derived, x = 100
From what I can figure out is because the variable x in your base class is public, the derived class inherits that variable. Therefor, when you .setX to a value, you change that variable in the derived class which is the same as within the base class. Which is what I could figure out.

Related

issue of derived class pointer casted to base class pointer and cast back

I am confused by a design that I saw recently. It initialize a derived class object in the main function and pass it as a base class object into a function. Then, inside the function that object pointer is casted back to the derived class again. Is this a design pattern or should it be avoid?
Also, a member variable exclusive to the derived class is used after the pointer being converted to the base class and back to the derived class again. How would the pointer easily find the variable after the process?
class Base
{
// something
}
class Derived : public Base
{
public:
void funcDerived() {return x;}
int x = 0;
}
int process(std::shared_ptr<Base> const& var)
{
auto new_var = std::dynamic_pointer_cast<Derived>(var);
return new_var->funcDerived();
}
int main()
{
auto derived = std::make_shared<Derived>(new Derived());
derived->x = 5;
process(derived);
return 0;
}
EDIT:
To add some details of this design, the base class is an abstract class while there are several derived classes for different version. Function process() is an API whose interface remains intact. Its behavior is controlled by conditional-compilation directives.

Derived Class Pointer Pointing To Base Class Object Using Static_Cast [duplicate]

This question already has answers here:
Downcasting using the 'static_cast' in C++
(3 answers)
Closed 3 years ago.
I have the below piece of code where I have a base class and a derived class. Both base class and derived class are having a function member sharing the same name. In the main(), I have typecasted a base class object to a derived class pointer and trying to call the function. To my utter surprise, it is calling the derived class function member. As far as I know, the base class object won't be having any information about the derived class object. So, how come my derived class pointer is still able to access the derived member function?
In the case of upcasting, I do understand derived class object will be having the contents of the base class that's why a base class pointer pointing to a derived class object will work as expected.
Can someone please help me in understanding how the derived class member function is getting called in this even when I am having a derived class pointer pointing to a base class object(which is having no information of derived class)?
#include<iostream>
using namespace std;
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
public:
void b()
{
cout << "derived";
}
};
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
d1->b();
return 0;
}
In your specific case, it's perfectly normal that b is called.
You have a pointer to Derived class, b it's not virtual. So the compiler will generate a call to Derived::b method.
Now, when b will be executed, as you put crap in the this pointer, it's undefined behavior.
But in your case, as you do not access the this pointer, there's no probleme.
Cast a base class to derived class results undefined behavior
As I know, the function doesn't takes any extra space in memory, it stores like the normal function. You can see a member function as a normal function with an extra this pointer. In general, which function to call is determined by the type of the object pointer. But the virtual function is different, it is called by virtual function table, in your code, there is no virtual function declared. So there is no virtual function table.
You can see your code in a different way:
void derived_b(derived* this)
{
cout << "derived";
}
void base_b(base* this)
{
cout << "base";
}
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
derived_b(d1);
return 0;
}
If you define some member in class, and use it in function b, it may cause some error.like
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
int a;
public:
derived(){a = 1;}
void b()
{
cout << "derived" << a;
}
};
your code in main() may cause error because the object b don't have any member in memory.

In C++, how to access the members of a nested class from a pointer to the drived class

Can you please explain me why I receive error trying to access the members of the nested class from the derived class:
class Base
{
public:
static int A;
class inside_Base {public: static int B;};
};
int Base::A = 1;
int Base::inside_Base::B = 2;
class Derived : public Base {};
then in main I have:
Base * p;
p = new Derived();
when I try to print p->inside_Base::B I receive below error:
error: 'Base::inside_Base' is not a base of 'Derived'
Thanks.
As #V.Kravchenko said, you should not use static members through created objects. There is no variables polymorphism, only the functions one.
Usually you do not need to refer to inside_Base through Derived, because you lie that the Base::inside_Base is a nested class of Derived. But if you want it very much, you can typedef it:
class Derived : public Base
{
public:
typedef Base::inside_Base inside_Base;
};
In this case you can write Derived::inside_Base::B, for example (checked in MSVC 9.0). But, of course, it has no polymorphism as the class is defined statically in compile time.
What means p->A? Why not p->inside_Base::B?
p->A is equivalent to Base::A. It is C++ feature that allow you to use static variables as non-static. Don't know why it is needed.
var->Class::member says that you want a member symbol from class Class related to var instance. It is needed to resolve ambiguous symbols that may be used with var. For example:
class Base
{
public:
int x = {1};
};
class Derived
{
public:
int x = {2};
};
void main()
{
Derived var
std::cout << var.x << " " << var.Base::x;
}
Out will be 2 1. In second call we want to get exactly Base's member.
So, p->inside_Base::B says that you want a B from exactly class inside_Base related to p variable. But inside_Base is not a p's class and not a derived one. You can ask: why compiler doesn't scan nested classes? I think that because nobody needs it. It will complicate compilation and will not benefit as it doesn't resolve any ambiguousness.

why I changed parent virtual function arguments in child hides the father function c++?

I made a class with virtual function f() then in the derived class I rewrote it like the following f(int) why can't I access the base class function throw the child instance ?
class B{
public:
B(){cout<<"B const, ";}
virtual void vf2(){cout<<"b.Vf2, ";}
};
class C:public B{
public:
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
int main()
{
C c;
c.vf2();//error should be vf2(2)
}
You have to do using B::vf2 so that the function is considered during name lookup. Otherwise as soon as the compiler finds a function name that matches while traversing the inheritance tree from child -> parent -> grand parent etc etc., the traversal stops.
class C:public B{
public:
using B::vf2;
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
You are encountering name hiding. Here is an explanation of why it happens ?
In C++, a derived class hides any base class member of the same name. You can still access the base class member by explicitly qualifying it though:
int main()
{
C c;
c.B::vf2();
}
You were caught by name hiding.
Name hiding creeps up everywhere in C++:
int a = 0
int main(int argc, char* argv[]) {
std::string a;
for (int i = 0; i != argc; ++i) {
a += argc[i]; // okay, refers to std::string a; not int a;
a += " ";
}
}
And it also appears with Base and Derived classes.
The idea behind name hiding is robustness in the face of changes. If this didn't exist, in this particular case, then consider what would happen to:
class Base {
};
class Derived: public Base {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
Derived d;
d.foo(1.0);
}
If I were to add a foo overload to Base that were a better match (ie, taking a double directly):
void Base::foo(double i) {
sleep(i);
}
Now, instead of printing 1, this program would sleep for 1 second!
This would be crazy right ? It would mean that anytime you wish to extend a base class, you need to look at all the derived classes and make sure you don't accidentally steal some method calls from them!!
To be able to extend a base class without ruining the derived classes, name hiding comes into play.
The using directive allows you to import the methods you truly need in your derived class and the rest are safely ignored. This is a white-listing approach.
When you overload a member function in a base class with a version in the derived class the base class function is hidden. That is, you need to either explicitly qualify calls to the base class function or you need a using declaration to make the base class function visible via objects of the derived class:
struct base {
void foo();
void bar();
};
struct derived: base {
void foo(int);
using base::foo;
void bar(int);
};
int main() {
derived().foo(); // OK: using declaration was used
derived().bar(); // ERROR: the base class version is hidden
derived().base::bar(); // OK: ... but can be accessed if explicitly requested
}
The reason this is done is that it was considered confusing and/or dangerous when a member function is declared by a derived function but a potenially better match is selected from a base class (obviously, this only really applies to member functions with the same number of arguments). There is also a pitfall when the base class used to not have a certain member function: you don't want you program to suddenly call a different member function just because a member function is being added to the base class.
The main annoyance with hiding member functions from bases is when there is a set of public virtual functions and you only want to override one of them in a derived class. Although just adding the override doesn't change the interface using a pointer or a reference to the base class, the derived class can possibly not used in a natural way. The conventional work-around for this to have public, non-virtual overload which dispatch to protected virtual functions. The virtual member function in the various facets in the C++ standard library are an example of this technique.

Enforce use of scope resolution operator when accessing base class member from derived class

I have a class Derived which is derived from class Base. In Derived's function, I can access protected members of Base. E.g., I can do this.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
i = 5;
}
}
My question is, is it possible to enforce the use of scope resolution operator when accessing base class member from derived class? The reason is that I want to make it clear in the code which variables are from the base class. The enforcement is so that I won't accidentally skip the scope resolution operator (I'm careless). I prefer not to use accessors since many members from the base class are required in the Derived class, making it tedious to code. I'm using MSVC 2010 by the way.
class Base
{
protected:
int i;
}
class Derived : class Base
{
void process()
{
Base::i = 5; //enforce so that i=5 won't compile
}
}
you can simulate it by introducing another scope:
class Base {
protected:
struct Data {int i;};
Data d_Base;
};
class Derived : class Base {
void process() {
d_Base.i = 5;
}
};
You cannot do it in the base class itself, no, there is no way you could enforce that. However, I am thinking of a trick which you could do in a derived class to enforce what you want, that is, if you declare a variable with the same name i in the derived class as a member, but of type, say, MyBadType, which is just an empty type, then i in derived will refer to it and there is really nothing the user could do with it. So he will HAVE TO qualify to get the base i. But this is naturally a joke, I mean, you don't want to fatten the size of your derived class just to enforce qualified names. Your goal itself is a bit dubious.
HTH,
Armen