warning on derived class member shadowing base class member - c++

C++ compilers warn when a local variable shadows another variable.
e.g. https://godbolt.org/g/TYYf8F
However none of the major C++ compilers warn when a member of a derived class shadows a member of the base class:
class A
{
int _memberVar = 2;
public:
virtual int memberVar()
{
return _memberVar;
}
};
class B : public A
{
int _memberVar = 3;
};
int main()
{
A* pB = new B();
return pB->memberVar(); // returns 2
}
see https://godbolt.org/g/fBMUAd
Is there a reason behind it?

Virtual is a mechanism in the caller of a function to decide which function to call. It does not make the function to somehow behave "virtual". Since you did not overwrite the function B::memberVar() it is still calling A::memberVar(), and this behaves as any other member function of A.

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.

Why can't a 'Base Class object' call it's own virtual function? C++

I've read about virtual functions in C++ and understood how they provide the programmer with access to the member function of derived class using a pointer of base class. (aka Polymorphism).
The questions that have been bothering me are:
Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)
In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
.
#include <iostream>
using namespace std;
class B
{
public:
void virtual display()
{ cout<<"Inside base class.\n"; }
};
class D : public B
{
public:
void display()
{ cout<<"Inside derived class.\n"; }
};
int main()
{
B *b;
D d;
//Line-22 b->display(); Why can't 'b' call it's own display()?
b = &d;
b->display();
system("pause");
return 0;
}
Output:
Inside derived class.
b is a pointer not an object. Initially it didn't point to anything (so indirecting through it is an error); after b = &d, it points to a D object, so using it to call a virtual function will call D's override.
The virtual dispatch mechanism is defined so that the function is chosen based on the type of the actual object that the pointer points to, not the declared type of the pointer. So if it pointed to a B object then it would call B::display; here, it points to a D object, so it calls D::display.
Why declare a function with a same name in the base class, if in the end it has to be declared virtual?
It needs to be declared in the base class so that, when using a pointer to the base class, the compiler knows that it exists. Whether calling the function through the pointer will call the base-class version, or a version overridden by a derived class, depends on the type of the object.
In the code below, if virtual display() is called with a base class pointer (Line 22), it shows an error.
That's because it doesn't point to anything, so using it is an error. If it were to point to a B object, then it would call the function declared in B.
B b_obj;
b = &b_obj;
b->display(); // "Inside base class"
Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
They're not; that's the usual way of calling them. But the pointer must point to a valid object for virtual dispatch to work.
I confess I don't quite understand your question #1. Declaring a virtual function in a base class allows derived classes to override that implementation.
There are tons of uses for this (just search for polymorphism, Liskov substitution etc.). As a simple (and contrived) example, consider this:
struct File
{
virtual void open() { some_code; }
virtual void close() { some_code; }
static std::unique_ptr<File> create();
};
struct DbgFile : File
{
virtual void open() { std::clog << "Opening"; File::open(); }
virtual void open() { std::clog << "Closing"; File::close(); }
};
std::unique_ptr<File> File::create()
{
#ifdef NDEBUG
return { new File };
#else
return { new DbgFile };
#endif
}
int main()
{
auto f = File::create();
f->open();
f->close();
}
The above main() uses the File interface, but in debug builds, it will actually work with an object of type DbgFile which logs all operations happening on it.
As to your question #2, the problem in your code is that b doesn't point anywhere. If you do this instead, it will work just fine:
int main()
{
B *b;
B bb;
D d;
b = &bb;
b->display(); // Outputs "Inside base class."
b = &d;
b->display(); // Outputs "Inside derived class."
// In addition, you can explicitly suppress dynamic dispatch:
b->B::display(); // Outputs "Inside base class."
return 0;
}
Why declare a function with a same name in the base class, if in the end it has to be declared virtual? (Note: I need answers with respect to the polymorphism aspect of virtual functions)
It's necessary because,base class has to know which function definition it needs to call at runtime. Its a kind of interface.
In the code below, if 'virtual display()' is called with a base class pointer (Line 22), it shows an error. Why are virtual functions in C++ so rigid w.r.t. not getting called by base class pointers?
Since the pointer is not initialized its throwing an error. Use like below.
Base baseObj1,*basePtr;
basePtr= &baseObj1;
basePtr->Display(); //Inside base class

Can't access public base member from derived pointer

Why does this code not compile? (gcc 4.7.0)
// Class with a simple getter/setter pair.
class Base {
public:
Base () : m_Value(0) { }
virtual ~Base () { }
// Getter
virtual int value () { return m_Value; }
// Setter
virtual void value (int Val) { m_Value = Val; }
private:
int m_Value;
};
// Derived class overrides the setter.
class Derived : public Base {
public:
void value (int Val) {
// do some stuff here...
}
};
int main()
{
Derived * instance = new Derived();
int x = instance->value(); // ERROR
return 0;
}
Build log:
test.cpp: In function 'int main()':
test.cpp:29:25: error: no matching function for call to 'Derived::value()'
test.cpp:29:25: note: candidate is:
test.cpp:21:7: note: virtual void Derived::value(int)
test.cpp:21:7: note: candidate expects 1 argument, 0 provided
Why does the compiler fail to see 'int value()' from Base when using Derived*?
Changing
Derived * instance = new Derived();
to
Base * instance = new Derived();
works (but I need the derived pointer in my case).
Also renaming the base getter/setter functions to say getValue() and setValue(int) works. I can use various workarounds for my code, but I was just curious as to why this code fails to compile.
This is how the language works: When a child class overrides a member of a name it hides all the non-overridden names in the parent. This is to prevent accidentally combining base and parent methods that should be overridden as sets.
You can put using Base::value; in your child class to bring in the parent methods.
The function value in the derived class hides the function in the base class.
You need to bring the base class functions into the scope of the derived class as:
class Derived : public Base {
public:
using Base::value; //<---- note this
void value (int Val) {
// do some stuff here...
}
};
Besides the other answers given, in addition to adding using Base::value in the child class, you can also do the following,
int x = instance->Base::value();
Where you specifically tell the compiler to use Base's value function. Although technically this works, it forces a bit of indirection and if you see yourself doing this often you may want to rethink how you are structuring your code.

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.

Call different classes in different time in same function

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.