This question already has answers here:
Why won't the C++ compiler disambiguate between an inherited public and an inherited private method with the same name?
(5 answers)
Closed 1 year ago.
In the code below the public method Base2::f() is expected to become a private member of the Derived class however the compiler complains about ambiguity.
The question is on the basic understanding of inheritance. I appreciate if someone can help to shed some light on it.
#include <iostream>
template <typename TDerived>
class Base1 {
public:
void f() { static_cast<TDerived &>(*this)->f_impl(); }
};
class Base2 {
public:
void f() { std::cout << "f()" << std::endl; }
};
class Derived : public Base1<Derived>, private Base2 {
public:
void f_impl() { std::cout << "f_impl()" << std::endl; }
};
int main() {
Derived d;
d.f();
}
Jarod42 rightfully posted the comment
The check of visibility (public/private) is done after the selection,
and so it is ambiguous
Here is a relevant section from cppreference
Member access does not affect visibility: names of private and
privately-inherited members are visible and considered by overload
resolution, implicit conversions to inaccessible base classes are
still considered, etc. Member access check is the last step after any
given language construct is interpreted. The intent of this rule is
that replacing any private with public never alters the behavior of
the program.
Related
This question already has answers here:
C++ "virtual" keyword for functions in derived classes. Is it necessary?
(9 answers)
Closed 2 years ago.
#include <iostream>
class base {
public:
virtual void print(){
std::cout << "base\n";
}
};
class dr : public base {
public:
void print(){
std::cout << "dr\n";
}
};
class last : public dr {
public:
void print(){
std::cout << "last\n";
}
};
int main(){
dr *d = new last();
d->print();
return 0;
}
In the above code, only the base class includes a virtual function.
dr and last do not include a virtual function and yet polymorphism is still working.
The output of this code is last. (It should have been dr without polymorphism kicking in).
Does this mean polymorphism works as long as some base class has a virtual function, even though non of the derived classes have one?
Both dr::print and last::print override base::print, they're virtual functions too; the keyword virtual is optional here.
(emphasis mine)
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
This question already has answers here:
Public virtual function derived private in C++
(3 answers)
Closed 6 years ago.
let's assume u have a class base and class A which inherits from base . base have a declaration of a pure virtual functions called getValue() which is public , and A contains the definition(implementation) of the functions which is set as private .
When trying to use the function getValue() from base reference or pointer (base& /base*) to an A object it access it even though it's declared as private
Because in C++, virtuality and access are orthogonal concerns. When the compiler sees a base* or base& and it needs to call getValue on it, then it's sufficient that the function is accessible in base.
The fact that A declares its (overriding) getValue as private is irrelevant. After all, how could it be relevant? When base.getValue() or base->getValue() is called, you don't know that you might be dealing with an A. That's the whole point of object-oriented programming in the first place!
This does not mean that it's good style to vary access specifiers within a class hierarchy, though, because it can be confusing. In fact, you should split your getValue into two different functions, one being virtual and the other one non-virtual.
Long story: C++ behaves very different from other popular programming languages here, because it actually allows and encourages private virtual functions. Virtual member functions should be private by default, and public member functions should be non-virtual by default, and call the private virtual ones if necessary. (The only exception is the destructor, of course.) Herb Sutter once called this the Non-Virtual Interface Idiom.
Example:
#include <iostream>
class Base
{
public:
virtual ~Base() {}
int getValue() const
{
int const value = doGetValue();
if (value < 0)
{
// error
}
return value;
}
private:
virtual int doGetValue() const = 0;
};
class A : public Base
{
private:
int doGetValue() const override
{
return 123;
}
};
int main()
{
Base* ptr = new A; // use std::unique_ptr in real code
std::cout << ptr->getValue() << "\n";
delete ptr;
}
This question already has answers here:
Why does a virtual function get hidden?
(6 answers)
Closed 8 years ago.
This is a continuation of my prior question. Note that the code below makes a virtual call at p->f(1.0) printing Derived::f(double).
#include <iostream>
#include <complex>
using namespace::std;
class Base
{
public:
virtual void f(double);
virtual ~Base() {};
};
void Base::f(double) { cout << "Base::f(double)\n"; }
class Derived : public Base {
public:
void f(std::complex<double>);
void f(double);
};
void Derived::f(std::complex<double>) { cout << "Derived::f(complex)\n"; }
void Derived::f(double) { cout << "Derived::f(double)\n"; }
int main()
{
Derived* p = new Derived;
p->f(1.0);
delete p;
}
If I just eliminate the member function void f(double); in Derived, the code makes a static call to Derived::f(std::complex<double>).
What was it that made the compiler change from a dynamic call in the first example to a static call in the second? I would appreciate some quote from the Standard.
Edit:
The answers to the question to which this was considered a dup don't cite the Standard, as I asked above. Thanks.
What was it that made the compiler change from a dynamic call in the first example to a static call in the second?
The lookup rules. Without the declaration of f(double) in derived (and lacking a using-declaration) the f(complex<double>) hides f(double) in the base. When the compiler does lookup for p->f(1.0) inside Derived, finds an overload and given a single option uses it. It never moves up to Base to check whether there are different overloads.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why is this not allowed in C++?
Why is this not allowed in C++...??
class base
{
private:
public:
void func()
{
cout<<"base";
}
};
class derived : private base
{
private:
public:
void func()
{
cout<<"derived";
}
};
int main()
{
base * ptr;
ptr = new derived;
((derived *)ptr)->func();
return 0;
}
I am getting an error
**61 C:\Dev-Cpp\My Projects\pointertest.cpp `base' is an inaccessible base of `derived'**
My question is that since func() is defined public in derived class and the statement
((derived *)ptr)->func(); is trying to display the func() of derived..Why is there an accessible issue due to mode of inheritance..How does mode of inheritance(private) affects the call although I already have public derived func() in derived class..?
If mode of inheritance is changed to public I get my desired result..But a case where func() is private in base(so as func() of base is not inherited) and also func() is public in derived and mode of inheritance is public why still am I getting my desired result..Shouldn I be getting an Compile error as in the previous case ??
I am totally confused ..Please tell me how the compiler works in this case..??
You can't let the base pointer point to the derived object when there is private inheritance.
Public inheritance expresses an isa relationship. Private inheritance on the other hand expresses a implemented in terms of relationship
Ther compile error refers to the line:
ptr = new derived;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ overload resolution
I ran into a problem where after my class overrode a function of its base class, all of the overloaded versions of the functions were then hidden. Is this by design or am I just doing something wrong?
Ex.
class foo
{
public:
foo(void);
~foo(void);
virtual void a(int);
virtual void a(double);
};
class bar : public foo
{
public:
bar(void);
~bar(void);
void a(int);
};
the following would then give a compile error saying there is no a(double) function in bar.
main()
{
double i = 0.0;
bar b;
b.a(i);
}
In class bar, add
using foo::a;
This is a common 'gotcha' in C++. Once a name match is found in the a class scope, it doesn't look further up the inheritance tree for overloads. By specifying the 'using' declaration, you bring all of the overloads of 'a' from 'foo' into the scope of 'bar'. Then overloading works properly.
Keep in mind that if there is existing code using the 'foo' class, its meaning could be changed by the additional overloads. Or the additional overloads could introduce ambiguity and and the code will fail to compile. This is pointed out in James Hopkin's answer.
That is the way the language used to work. Prior to the using keyword, if you overrode one overloaded function, you had to overload them all:
class bar : public foo
{
public:
bar(void);
~bar(void);
a(int);
a(double d) { foo::a(d); } // add this
}
This annoyed enough people that the language committee added the using feature, but some old habits die hard; and the habitués† have a good argument.
As James Hopkins points out, by adding using, the programmer is expressing the intention that the derived class will, without warning, add any future overrides of foo::a() to its list of acceptable signatures.
Here is an example of what he describes:
#include <iostream>
class Base {
public:
virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
// virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
virtual ~Base() {}
};
class Derived : public Base {
public:
// using Base::f; // (2)
void f(double) { std::cout << "Derived::Double!" << std::endl; }
};
int main(int, char **) {
Derived d;
d.f(21);
return 0;
}
The output will be "Derived::Double!" because the compiler will promote the integer argument to a double. g++ 4.0.1 -Wall will not warn that this promotion occurred.
Uncomment (1) to simulate a future change to Base adding the method Base::f(int). The code compiles, again without warning even with -Wall, and "Derived::Double!" remains the output.
Now uncomment (2) to simulate a decision by the Derived programmer to include all Base::f signatures. The code compiles (without warnings), but the output is now "Base::Int!".
—
† I cannot think of an English word for "those who have the habit" and "addicted" is much too strong.
It is by design. Overload resolution is restricted to a single scope. It prevents some nasty cases of valid code changing meaning when additional functions are added to a base class or to namespace scope.