I am learning and playing around with inheritance and abstract classes. I've run into a predicament that I would appreciate some clarifications on.
I am trying to override a non-virtual function from an abstract grandparent class. I am getting an error saying that 'member function declared with 'override' does not override a base class member.
I can call the original non-virtual function from child class instances in main(), but not override them in child classes?
Here's the code.
UPDATE:
Error went away when I marked the function as virtual, I would still appreciate an explanation as to why that virtual is necessary?
#include <iostream>
using namespace std;
class A
{
public:
virtual string GetClassName() = 0;
void foo(); // <--- this is the problem function
{
cout << "foo" << endl;
}
};
class B : public A
{
public:
string GetClassName() override
{
return "B";
}
};
class C1 : public B
{
public:
string GetClassName() override
{
return "C";
}
};
class C2 : public B
{
public:
void foo() override // ERROR:member function declared with override does not override a base class member.
{
cout << "foo c1" << endl;
}
};
// testing interface
void printName(A* ptr)
{
cout << ptr->GetClassName() << endl;
}
int main()
{
B* b = new B();
C1* c1 = new C1();
C2* c2 = new C2();
printName(b); // prints B
printName(c1); // prints C
printName(c2); // prints B
b->foo(); // prints foo, inherited directly from abstract class
c1->foo(); // prints foo, inherited directly from abstract class
c2->foo(); // ??
}
You cannot override a non-virtual function. It is as simple as that.
Methods in child classes can hide methods of parent classes when they have the same name, for example:
struct A {
void foo(){}
};
struct B : A {
void foo() {}
};
But thats not overriding. To override the method must be virtual. Thats one of the conditions that the override specifier helps to check:
struct A {
virtual void foo(){}
};
struct B : A {
void foo() override {} // <- error if A::foo is not virtual
};
PS: I have seen poor tutorials, that use the first example and call that overriding. Thats just wrong.
Related
I have been watching several videos, and I have come to know how virtual function calls are processed through late binding.
In early binding, for lines like ptr->func(...), the compiler reviews the data type for ptr and looks in the corresponding class for the func(...) definition.
While during late binding for virtual functions, ptr address is accessed, and then the definition is looked up in the corresponding class.
If I am right about the mechanism I have just mentioned, then why does the following code produce an error?
class A{
public:
void func(){
}
};
class B: public A{
public:
virtual void f4(){
cout<<"Cunt"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Also, why does the below code produce the output base instead of the output derived?
class A{
public:
void f4(){
cout<<"base"<<endl;
}
};
class B: public A{
public:
virtual void f4(){
cout<<"derived"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Please help. Am I wrong about the mechanism?
In class A, the function f4 should be defined as virtual too:
class A {
public:
virtual void f4(){
std::cout << "base" << std::endl;
}
};
In your case, f4 is non-virtual function, due to non-virtual inheritance.
One more thing, derived virtual functions should be mark as override, and the virtual is not necessary:
class B : public A {
public:
void f4() override {
std::cout << "derived" << std::endl;
}
};
If you would try to mark f4 in B as override without making it virtual in A first, you would get the compilation error: error: ‘virtual void B::f4()’ marked ‘override’, but does not override- which means that you won't be able to access it using A class pointer.
Side note: read the following post: Why is "using namespace std;" considered bad practice?
In your first example, A does not have a method named f4(), so the call to ptr->f4() is not valid.
In your second example, A::f4() is not marked as virtual, so the call to ptr->f4() does not perform virtual dispatch, and so calls A::f4() rather than B::f4().
The solution to both problems is the same - make f4() be virtual in A, and have B override it, eg:
class A{
public:
virtual void f4() {
cout << "base" << endl;
}
};
class B: public A{
public:
void f4() override {
cout << "derived" << endl;
}
};
int main(){
A* ptr;
B obj;
ptr = &obj;
ptr->f4();
return 0;
}
Can I have a virtual function in the base class and some of my derived classes do have that function and some don't have.
class A{
virtual void Dosomething();
};
class B : public A{
void Dosomething();
};
class C : public A{
//Does not have Dosomething() function.
};
From one of my c++ textbook:
Once a function is declared virtual, it remains virtual all the way down the inheritance, even if the function is not explicitly declared virtual when the derived class overrides it.
When the derived class chooses not to override it, it simply inherits its base class's virtual function.
Therefore to your question the answer is No. Class c will use Class A's virtual function.
Derived classes do not have to implement all the virtual functions, unless it is a pure virtual function. Even in this case, it will cause an error only when you try to instantiate the derived class( without implementing the pure virtual function ).
#include <iostream>
class A{
public :
virtual void foo() = 0;
};
class B: public A{
public :
void foo(){ std::cout << "foo" << std::endl;}
};
class C: public A{
void bar();
};
int main() {
//C temp; The compiler will complain only if this is initialized without
// implementing foo in the derived class C
return 0;
}
I think the closest you might get, is to change the access modifier in the derived class, as depicted below.
But, I would consider it bad practice, as it violates Liskov's substitution principle.
If you have a situation like this, you might need to reconsider your class design.
#include <iostream>
class A {
public:
virtual void doSomething() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
void doSomething() override { std::cout << "B" << std::endl; };
};
class C : public A {
private:
void doSomething() override { std::cout << "C" << std::endl; };
};
int main(int argc, char **args) {
A a;
a.doSomething();
B b;
b.doSomething();
C c;
//c.doSomething(); // Not part of the public interface. Violates Liskov's substitution principle.
A* c2 = &c;
c2->doSomething(); // Still possible, even though it is private! But, C::doSomething() is called!
return 0;
}
Let's consider the following code:
#include <iostream>
class Base
{
public:
void foo() //Here we have some method called foo.
{
std::cout << "Base::foo()\n";
}
};
class Derived : public Base
{
public:
void foo() //Here we override the Base::foo() with Derived::foo()
{
std::cout << "Derived::foo()\n";
}
};
int main()
{
Base *base1 = new Base;
Derived *der1 = new Derived;
base1->foo(); //Prints "Base::foo()"
der1->foo(); //Prints "Derived::foo()"
}
If I have the above stated classes, I can call the foo method from any of Base or Derived classes instances, depending on what ::foo() I need. But there is some kind of problem: what if I need the Derived class instance, but I do need to call the Base::foo() method from this instance?
The solve of this problem may be next:
I paste the next method to the class Derived
public:
void fooBase()
{
Base::foo();
}
and call Derived::fooBase() when I need Base::foo() method from Derived class instance.
The question is can I do this using using directive with something like this:
using Base::foo=fooBase; //I know this would not compile.
?
der1->Base::foo(); //Prints "Base::foo()"
You can call base class method using scope resolution to specify the function version and resolve the ambiguity which is useful when you don't want to use the default resolution.
Similar (Not exactly same case) example is mentioned # cppreference
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}
Take a look at the code. I have interface which looks like this:
class Abstract_base {
public:
virtual ~Abstract_base() {}
virtual void f1 () = 0;
virtual void f2 () = 0;
};
Base class looks like this:
class Base : public Abstract_base {
public:
virtual ~Base() {}
virtual void f1 () override { cout << "f1" << endl; }
virtual void f2 () override { cout << "f2" << endl; }
};
and I have two derived class, like this:
class Derived_1 : public Base {
public:
virtual ~Derived_1() {}
private:
virtual void f2 () override { cout << "Derived_1::f2 ()" << endl; }
};
class Derived_2 : public Base {
public:
virtual ~Derived_2() {}
private:
virtual void f1 () override { cout << "Derived_2::f1 ()" << endl; }
};
and finally I have Handler class which looks like this:
class Handler {
public:
Handler (Abstract_base& b) : base (b) {}
virtual ~Handler() {}
void process_1 () {
base.f1 ();
}
void process_2 () {
base.f2 ();
}
private:
Abstract_base& base;
};
And main.cpp looks like this:
int main (int argc, char** argv) {
Derived_1 der1;
der1.f2 ();
Derived_2 der2;
der2.f1 ();
Handler handler1 (der1);
handler1.process_2 ();
Handler handler2 (der2);
handler2.process_1 ();
return 0;
}
Of course code will not compile because der1.f2 () and der2.f1 () are private, but if I comment out these two instructions and leave the handler1.process_2 () and handler2.process_1 () instructions, code will compile and produce output:
Derived_1::f2 ()
Derived_2::f1 ()
Question:
How can I prevent from calling these two private member functions using reference to the Abstract_base class? I just don't want the user have access to the f2 () in Derived_1 and f1() in Derived_2.
As far as I know I could not use delete keyword for Derived_1::f2 () and Derived_2::f1 ().
Could you suggest me a solution for this problem?
Solution
I know that one of the solution could be make Handler a template class like this:
template <class B>
class Handler_templ {
public:
Handler_templ (B& b) : base (b) { }
virtual ~Handler_templ() {}
void process_1 () {
base.f1 ();
}
void process_2 () {
base.f2 ();
}
private:
B& base;
};
and use it like this:
Handler_templ<Derived_1> h1 (der1);
Handler_templ<Derived_2> h2 (der2);
h1.process_2 ();
h2.process_1 ();
What surprising me is why using Handler class I am able to invoke these private member function? For any suggestions I would be very grateful.
Sincerely,
Artur
You can't prevent from calling these two private member functions using reference to the Abstract_base class. When you access the methods by reference or pointer of the base class, the access rights of derived class will not be considered. (How can the compiler know that?)
According to Liskov Substitution Principle (LSP) ,
Functions that use pointers or references to base classes must be able
to use objects of derived classes without knowing it.
_"How can I prevent from calling these two private member functions using reference to the Abstract_base class? I just don't want the user have access to the f2() in Derived_1 and f1() in `Derived_2"._
There's no way to hide these functions by using the scope operators through a derived class declaration.
"What surprising me is why using Handler class I am able to invoke these private member function?"
As for your samples
class Base : public Abstract_base {
public:
virtual ~Base() {}
virtual void f1 () override { cout << "f1" << endl; }
virtual void f2 () override { cout << "f2" << endl; }
};
class Derived_1 : public Base {
public:
virtual ~Derived_1() {}
private:
virtual void f2 () override { cout << "Derived_1::f2 ()" << endl; }
};
class Derived_2 : public Base {
public:
virtual ~Derived_2() {}
private:
virtual void f1 () override { cout << "Derived_2::f1 ()" << endl; }
};
it's perfectly OK to override a public base class function, using a private function in the derived class.
These function overrides will still be visible via the Base/Abstract_base class interfaces.
The private scope specifier makes them just inaccessible for directly calling clients.
You cannot do that. You cannot prevent two things:
Derived_1 der1;
((Abstract_base*)&der1)->f2 (); // 1
And the pointer or reference conversion:
Derived_1 d;
Abstract_base* bp = &d; // 2
Abstract_base& ref = d; // 2
C++ doesn't have provision to stop conversion to base pointer/reference, or to perform object-slicing to base. Neither C++ mandates that derived class must implement virtual function in specified protection level.
Consider a base class class Base which has a function virtual void foo(void). This function is implemented in Base; i.e. is not pure virtual.
Is there a pattern I can use which when inheriting from this class, i.e. class Child : public Base, compels me to override foo?
Other than making it a pure virtual function, there is no way to make the override required.
Note that the fact that a function is marked pure virtual does not mean that it cannot have an implementation in the base class - it means only that the derived class must override it.
struct Base {
virtual void foo() = 0; // foo() is pure virtual
};
struct Derived : public Base {
void foo() { // Derived overrides the pure virtual
cout << "Hello ";
Base::foo(); // Call the implementation in the base
cout << endl;
}
};
void Base::foo() {
cout << " world";
}
int main() {
Derived d;
d.foo();
return 0;
}
This prints "Hello world", with the "world" part coming from the implementation in the base class.
Demo.
C++11 introduced the override keyword to help with this:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo() override; // error! Base::foo is not virtual
};
However you can not write this in Base itself to get the same effect; i.e. there is no mustoverride specifier. Ultimately, it is none of Base's business as to what derived classes do or don't override.
You can keep Base abstract whilst providing a "default" definition for your pure virtual functions:
struct Base
{
virtual void foo() = 0;
};
void Base::foo() {}
struct Derived : Base {}; // error! does not override Base::foo
struct Derived2: Base
{
virtual void foo() override
{
Base::foo(); // invokes "default" definition
}
};
This will be an acceptable solution if you are content for the entire base type to be rendered uninstantiable.
A pure-virtual member function can still have a body. The only caveat is that it must be defined outside the class definition. This is perfectly legal C++:
#include <iostream>
struct Base
{
virtual void foo() const = 0;
};
void Base::foo() const
{
std::cout << "Base!\n";
}
struct Derived : Base
{
// Uncomment following line to remove error:
//virtual void foo() const override { std::cout << "Derived\n"; Base::foo(); }
};
int main()
{
Derived d;
d.foo();
}
Live example
Notice that this makes Base an abstract class in all respects, i.e. it's impossible to instantiate Base directly.
Yes, actually there is:
#include <iostream>
class Base
{
public:
virtual void someFun() {std::cout << "Base::fun" << std::endl;}
virtual ~Base() {}
};
class AlmostBase : public Base
{
public:
virtual void someFun() = 0;
};
class Derived : public AlmostBase
{
public:
virtual void someFun() {std::cout << "Derived::fun" << std::endl;}
};
int main()
{
Derived *d = new Derived();
d->someFun();
delete d;
}
If you uncomment the someFun from Derived the compiler will complain ...
You introduce an intermediary class AlmostBase which has the function as pure virtual. This way you can have Base objects too, and the only drawback now is that all your classes will need to inherit from the intermediary base.
you can make the base method throw an exception when called, then the class must override it to avoid the parent execution.
this is used in the MFC FrameWork for example
// Derived class is responsible for implementing these handlers
// for owner/self draw controls (except for the optional DeleteItem)
void CComboBox::DrawItem(LPDRAWITEMSTRUCT)
{ ASSERT(FALSE); }
void CComboBox::MeasureItem(LPMEASUREITEMSTRUCT)
{ ASSERT(FALSE); }
int CComboBox::CompareItem(LPCOMPAREITEMSTRUCT)
{ ASSERT(FALSE); return 0; }
those methods must be inherited if the control is owner drawn it is responsible for the measuer, draw,... if you missed it while you are testing the function you will get an assert or exception with useful information thrown.