C++ method only visible when object cast to base class? - c++

It must be something specific in my code, which I can't post. But maybe someone can suggest possible causes.
Basically I have:
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
};
CChild *pChild = ...
pChild->doIt(123); //FAILS compiler, no method found
CParent *pParent = pChild;
pParent->doIt(123); //works fine
How on earth?
EDIT: people are talking about shadowing/hiding. But the two versions of doIt have different numbers of parameters. Surely that can't confuse the compiler, overloads in child class which can't possibly be confused with the parent class version? Can it?
The compiler error I get is:
error C2660: 'CChild::doIt' : function does not take 1 argument

You have shadowed a method. For example:
struct base
{
void method(int);
void method(float);
};
struct derived : base
{
void method(int);
// base::method(int) is not visible.
// base::method(float) is not visible.
};
You can fix this with a using directive:
class derived : public base
{
using base::method; // bring all of them in.
void method(int);
// base::method(int) is not visible.
// base::method(float) is visible.
};
Since you seem insistent about the number of parameters, I'll address that. That doesn't change anything. Observe:
struct base
{
void method(int){}
};
struct derived : base
{
void method(int,int){}
// method(int) is not visible.
};
struct derived_fixed : base
{
using base::method;
void method(int,int){}
};
int main(void)
{
{
derived d;
d.method(1, 2); // will compile
d.method(3); // will NOT compile
}
{
derived_fixed d;
d.method(1, 2); // will compile
d.method(3); // will compile
}
}
It will still be shadowed regardless of parameters or return types; it's simply the name that shadows. using base::<x>; will bring all of base's "<x>" methods into visibility.

You are hitting a classic problem. You need using CParent::doIt; in your CChild class. I'll scrounge up the duplicate questions.
Edit:
Here's my answer to essentially the same question: Overriding a Base's Overloaded Function in C++

I have never done this without having that method in the base class before. I think that adding "using CLASS::METHOD" in derived class will give you access to the other version of the overloaded method.
class CParent
{
public:
void doIt(int x);
};
class CChild : public CParent
{
public:
void doIt(int x,int y,int z);
using CParent::doIt;
};

The problem is CChild doesn't actually inherit from CParent.
And so it doesn't have a doIt method that takes only one argument.

When you override a function in the derived class, only that function in the derived class is visible to the user of that class. The base class version becomes hidden.
Therefore, your pChild pointer calling doIt(int x) will fail since you are using a derived class pointer to call the base class function. The pParent pointer calling doIt(int x) will work since you are using a base class pointer to call the base class function. Even though you have a child object being pointed to by a parent pointer (upcasted), the class type here is determined by the declaration of the pointer which is a CParent.
To be able to call that base class function using the derived class pointer, you can:
Qualify the base class name in the function call, as in the following:
pChild->CParent::doIt(123);
Use a using directive to bring the function name from the base class into the derived class, as seen in the previous posts.

I understand that this behavior is to give you flexibility to override the behavior of base class method in your derived class.
Lets assume that you have a function foo(int) in base class and you want to change the behavior of this function in your derived class. Now if the base class method is not hidden by your derived class method (which has same prototype as that of base class's method), it will introduce ambiguity in overload resolution.

The method in your child class has a different number of arguments than what you're trying to pass into it. Could it be related to that?

Related

C++ : Semantic issue on a child class with same named method

This is a question about designing classes in C++.
My base class have virtual final method with parameters, the name of it is basically "update". In a child class, I wanted to use a higher level way to update the object, so I made a method called "update" too (for convenience), but this one have no parameter. And Clang warns me the method is hiding a base class method. In my point of view, I'm not totally agree with this, because the signature is different, it should just complete the overloading.
Is there a good reason to not do that ?
The warning is telling you that the function in the derived class makes it more difficult to call the original base class function on an object of the derived type:
class Base {
public:
virtual void update(int param) final;
};
class Derived : public Base {
public:
void update();
};
void f(Derived& obj) {
obj.update(2); // Error!
// Name lookup for update finds only Derived::update,
// which takes no arguments
}
To "unhide" the base class function, so that the derived class acts as though it has both overloads, use a using directive:
class Derived : public Base {
public:
void update();
using Base::update;
};

Private overriden virtual functions in derived class

Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.

c++ derived functions vs. base functions

Is there a way you can invoke a member function of a base class upon a class derived from it?
Class Bass{
public:
void func();
};
Class Derived: public Base{
public:
void func();
};
I have a practice midterm, and I suspect no, because how would the Base class know about the Derived, but I am not sure.
Is there a way you can invoke a member function of a base class upon a class derived from it?
Not sure exactly what you mean by this, but given your Base and Derived classes you can do the following. Just make sure you use a reference or pointer, not pass-by-value because of the slicing problem.
Call Base::func() from within Derived::func():
void Derived::func()
{
Base::func();
}
Call Base::func() explicitly on a Derived object:
Derived d;
d.Base::func();
I [...] am wondering if you could do something like Base::func(Derived d)
As others have pointed out, you can do this using a forward declaration:
// Tell the compiler "Derived" is a class name.
class Derived;
class Base
{
// Can use the class name since it has been declared.
void func(Derived& derived);
};
// Define the class named "Derived".
class Derived : public Base
{
// ...
};
// Use the derived class.
void Base::func(Derived& derived)
{
// For this bit to work, the definition of `Derived` must
// be visible at this point (like putting the class above
// or including your "Derived.h" from "Base.cpp").
derived.some_derived_method();
}
However, you won't be able to define the Base::func(Derived&) directly in the class definition since you need to finished defining Base and to define Derived first.
if I understand correctly, you need to call base function with derived parameter?
You can do it only using forward declaration and passing derived object by pointer or ref.
class Derived;
class Base{
public:
void func(Derived&);
};
You should be able to do something like this:
class Derived;
class Base {
public:
void func();
void func(Derived);
};
class Derived : public Base {
public:
void func();
};
void
Base::func(Derived D) {
}
It is okay to use incomplete types in the Base's member function declarations, but you must provide the complete type before their definition.
You can use forward declaration of Derived class:
class Derived;
First of all, do you mean methods on an object, or static class methods?
Secondly, the answer is: it depends what the object you're invoking the method call on is. This is the nature of polymorphism: if your object is of type 'Derived', then even if it has been cast to a 'Base' the method call will still invoke the Derived version of func.
Is that what you were asking?

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.

What does C++ using mean inside a class?

What does it mean to have a using inside a class definition?
class myClass {
public:
[...]
using anotherClass::method;
};
That declaration unhides a base class member. This is most often used to allow overloads of a member function. Example:
class Base {
public:
void method() const;
};
class Derived : public Base {
public:
void method(int n) const;
// Without the using, you would get compile errors on d.method();
using Base::method;
};
The case I've seen it:
class A
{
void foo(int);
void foo(float);
}
class B : public A
{
void foo(string);
}
B b;
b.foo(12); // won't work!
Because I have implemented a new foo function in B with a different signature it hides the foo functions from A. In order to override this behavior I would do:
class B : public A
{
void foo(string);
using A::foo;
}
Most often, syntax like this is used like so:
class derived : public base {
public:
[...]
using base::method;
};
The using declaration here unhides a member declaration from the parent class. This is sometimes necessary if another member declaration in derived may hide the member from base.
If anotherClass is a base class that contains a member function like
virtual void f();
and you decide to overload the function in the derived class like
virtual void f(int);
it "hides" f() in the base class. Calling f() through a pointer to the derived class for example, would result in an error, since the compiler does not "see" the version of f() taking no arguments from the base class anymore.
By writing
using Base::f;
you can bring the base classes function back into scope, thus enabling overload resolution as you might have expected it to work in the first place.