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;
}
Related
I did a simple test today:
struct C{virtual void f()=0;};
void C::f(){printf("weird\n");}
The program is OK, but is weird to me, when we use =0 it means the function body should be defined in the inherited classes, but it seems I can still give it implementation function.
I tried both GCC and VC, both OK. So it seems to me this should be part of C++ standard.
But why this is not a syntax error?
A reason I could think of is like C# having both 'interface' and 'abstract' keywords, interface can't have an implementation, while abstract could have some implementations.
Is this the case for my confusion, that C++ should support such a kind of weird syntax?
C++ Supports pure virtual functions with an implementation so class designers can force derived classes to override the function to add specific details , but still provide a useful default implementation that they can use as a common base.
Classic example:
class PersonBase
{
private:
string name;
public:
PersonBase(string nameIn) : name(nameIn) {}
virtual void printDetails() = 0
{
std::cout << "Person name " << name << endl;
}
};
class Student : public PersonBase
{
private:
int studentId;
public:
Student(string nameIn, int idIn) : PersonBase(nameIn), studentId(idIn) { }
virtual void printDetails()
{
PersonBase::printDetails(); // call base class function to prevent duplication
std::cout << "StudentID " << studentId << endl;
}
};
Others mentioned language consistency with the destructor, so I'll go for a software engineering stand-point:
It's because the class you are defining may have a valid default implementation, but calling it is risky/expansive/whatever. If you don't define it as pure virtual, derived classes will inherit that implementation implicitly. And may never know until run-time.
If you define it as pure virtual, a derived class must implement the function. And if it's okay with the risk/cost/whatever, it can call the default implementation statically as Base::f();
What's important is that it's a conscious decision, and the call is explicit.
Basically, the best of both worlds (or the worst...).
The derived class is required to implement the pure virtual method, the designer of the base class requires this for some reason. And the base class also provides a default implementation of this method that, if the derived class desires or requires it, can be used.
So some sample code could look like;
class Base {
public:
virtual int f() = 0;
};
int Base::f() {
return 42;
}
class Derived : public Base {
public:
int f() override {
return Base::f() * 2;
}
};
So what is a common use case...
A common use case for this technique is related to the destructor - basically the designer of the base class desires that it is an abstract class, but none of the methods make much sense as being pure virtual functions. The destructor is a feasible candidate.
class Base {
public:
~Base() = 0;
};
Base::~Base() { /* destruction... */ }
A pure virtual function must be overriden in subclasses. However, you can provide a default-implementation, that will work for sub-classes, but might not be optimal.
A constructed use case is for abstract shapes, e.g.
class Shape {
public:
virtual Shape() {}
virtual bool contains(int x, int y) const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual int area() const = 0;
}
int Shape::area() const {
int a = 0;
for (int x = 0; x < width(); ++x) {
for (int y = 0; y < height(); ++y) {
if (contains(x,y)) a++;
}
}
return a;
}
The area method will work for any shape, but is highly inefficient. Subclassers are encouraged to provide a suitable implementation, but if there is none available, they still can explicitely call the base class's method
Pure virtual means "child must override".
So:
struct A{ virtual void foo(){}; };
struct B:A{ virtual void foo()=0; };
struct C:B{ virtual void foo(){}; };
struct D:C{ virtual void foo()=0; };
void D::foo(){};
struct E:D{ virtual void foo(){D::foo();}; };
A has a virtual foo.
B makes it abstract. Before making an instance, derived types must implement it now.
C implements it.
D makes it abstract, and adds an imllementation.
E implements it by calling D's implementation.
A, C and E can have instances created. B and D cannot.
The technique of abstract with implementation can be used to provide a partial or inefficient implementation that derived types can call explicitly when they want to use it, but do not get "by default" because that would be ill advised.
Another intersting use case is where the parent interface is in flux, and tue code base is large. It has a fully functional implementation. Children who use the default must repeat the signature and forward explicitly to it. Those that want to override simply override.
When the base class sigrnature changes, the code will fail to compile unless every child either explicitly calls the default or properly overrides. Prior to the override keyword this was the only way to ensure you did not accidentally create a new virtual function instead of overriding a parent, and it remains the only way where the policy is enforced in the parent type.
Please note that you cannot instantiate an object with pure virtual methods.
Try to instantiate:
C c;
with VC2015, there is an error as expected:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): error C2259: 'C': cannot instantiate abstract class
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: due to following members:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: 'void C::f(void)': is abstract
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(6): note: see declaration of 'C::f'
To answer your question:
The mechanisms only declares the function to be pure virtual, but there is still the virtual function table and the baseclass. It will avoid you instanciate Baseclass (C), but does not avoid using it:
struct D : public C { virtual void f(); };
void D::f() { printf("Baseclass C::f(): "); C::f(); }
...
D d;
d.f();
The destructor must be defined, even if it is pure virtual. If you don't define the destructor the compiler will generate one.
Edit: you can't leave destructor declared without define, will cause link error.
You can anyway call the body of the function from derived classes.
You can implement the body of a pure virtual function to provide a default behavior, and at the same time you want that the designer of the derived class use that function explicitly.
This question already has answers here:
Private virtual method in C++
(5 answers)
Closed 2 years ago.
considering below example
#include <iostream>
#include <string>
class A
{
public:
virtual void foo() { std::cout<< "FOO A\n"; }
private:
void bar() { std::cout<< "BAR A\n"; }
virtual void vbar() { std::cout<< "VBAR A\n"; }
};
class B : public A
{
public:
void foo() { std::cout<< "FOO B\n"; bar(); vbar(); }
private:
void bar() { std::cout<< "BAR B\n"; }
virtual void vbar() { std::cout<< "VBAR B\n"; }
};
int main()
{
A* b = new B();
b->foo();
}
The output will give us
FOO B
BAR B
VBAR B
Since its simple example first that come to my mind I cant figure out any private virtual method use case. In case of public virtual method, the base pointer class interface will adapt to its defined vtable, but as in given example for private virtuals it doesnt matter
One possible use is for letting a base class define a structure, and having derived classes implement the behaivour of the components of said structure (the template method pattern). For example,
struct foo
{
void do_stuff() {
// defines order in which some operations are executed
do_op1();
do_op1();
do_op3();
}
private:
// These don't have to be pure virtual. A base,
// default implementation could also be provided.
virtual void do_op1() = 0;
virtual void do_op2() = 0;
virtual void do_op3() = 0;
};
// implements the operations
struct foo1 : foo
{
private:
void do_op1() override { ... }
void do_op2() override { ... }
void do_op3() override { ... }
};
The virtual methods are private because it does not make sense to call them in isolation. The base class knows when and how to call them.
There are probably simpler and better ways of implementing this in "modern C++", but this kind of thing might have been seen in the 90s and 00s.
There are situations where it might be useful, some argue, that it should be the prefered method, when possible, like Herb Sutter:
Guideline #2: Prefer to make virtual functions private.
...This lets the derived classes override the function to customize the behavior as needed, without further exposing the virtual functions directly by making them callable by derived classes (as would be possible if the functions were just protected). The point is that virtual functions exist to allow customization; unless they also need to be invoked directly from within derived classes' code, there's no need to ever make them anything but private. But sometimes we do need to invoke the base versions of virtual functions (see the article "Virtually Yours"[5] for an example), and in that case only it makes sense to make those virtual functions protected, thus:
Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected...
http://www.gotw.ca/publications/mill18.htm
I did a simple test today:
struct C{virtual void f()=0;};
void C::f(){printf("weird\n");}
The program is OK, but is weird to me, when we use =0 it means the function body should be defined in the inherited classes, but it seems I can still give it implementation function.
I tried both GCC and VC, both OK. So it seems to me this should be part of C++ standard.
But why this is not a syntax error?
A reason I could think of is like C# having both 'interface' and 'abstract' keywords, interface can't have an implementation, while abstract could have some implementations.
Is this the case for my confusion, that C++ should support such a kind of weird syntax?
C++ Supports pure virtual functions with an implementation so class designers can force derived classes to override the function to add specific details , but still provide a useful default implementation that they can use as a common base.
Classic example:
class PersonBase
{
private:
string name;
public:
PersonBase(string nameIn) : name(nameIn) {}
virtual void printDetails() = 0
{
std::cout << "Person name " << name << endl;
}
};
class Student : public PersonBase
{
private:
int studentId;
public:
Student(string nameIn, int idIn) : PersonBase(nameIn), studentId(idIn) { }
virtual void printDetails()
{
PersonBase::printDetails(); // call base class function to prevent duplication
std::cout << "StudentID " << studentId << endl;
}
};
Others mentioned language consistency with the destructor, so I'll go for a software engineering stand-point:
It's because the class you are defining may have a valid default implementation, but calling it is risky/expansive/whatever. If you don't define it as pure virtual, derived classes will inherit that implementation implicitly. And may never know until run-time.
If you define it as pure virtual, a derived class must implement the function. And if it's okay with the risk/cost/whatever, it can call the default implementation statically as Base::f();
What's important is that it's a conscious decision, and the call is explicit.
Basically, the best of both worlds (or the worst...).
The derived class is required to implement the pure virtual method, the designer of the base class requires this for some reason. And the base class also provides a default implementation of this method that, if the derived class desires or requires it, can be used.
So some sample code could look like;
class Base {
public:
virtual int f() = 0;
};
int Base::f() {
return 42;
}
class Derived : public Base {
public:
int f() override {
return Base::f() * 2;
}
};
So what is a common use case...
A common use case for this technique is related to the destructor - basically the designer of the base class desires that it is an abstract class, but none of the methods make much sense as being pure virtual functions. The destructor is a feasible candidate.
class Base {
public:
~Base() = 0;
};
Base::~Base() { /* destruction... */ }
A pure virtual function must be overriden in subclasses. However, you can provide a default-implementation, that will work for sub-classes, but might not be optimal.
A constructed use case is for abstract shapes, e.g.
class Shape {
public:
virtual Shape() {}
virtual bool contains(int x, int y) const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual int area() const = 0;
}
int Shape::area() const {
int a = 0;
for (int x = 0; x < width(); ++x) {
for (int y = 0; y < height(); ++y) {
if (contains(x,y)) a++;
}
}
return a;
}
The area method will work for any shape, but is highly inefficient. Subclassers are encouraged to provide a suitable implementation, but if there is none available, they still can explicitely call the base class's method
Pure virtual means "child must override".
So:
struct A{ virtual void foo(){}; };
struct B:A{ virtual void foo()=0; };
struct C:B{ virtual void foo(){}; };
struct D:C{ virtual void foo()=0; };
void D::foo(){};
struct E:D{ virtual void foo(){D::foo();}; };
A has a virtual foo.
B makes it abstract. Before making an instance, derived types must implement it now.
C implements it.
D makes it abstract, and adds an imllementation.
E implements it by calling D's implementation.
A, C and E can have instances created. B and D cannot.
The technique of abstract with implementation can be used to provide a partial or inefficient implementation that derived types can call explicitly when they want to use it, but do not get "by default" because that would be ill advised.
Another intersting use case is where the parent interface is in flux, and tue code base is large. It has a fully functional implementation. Children who use the default must repeat the signature and forward explicitly to it. Those that want to override simply override.
When the base class sigrnature changes, the code will fail to compile unless every child either explicitly calls the default or properly overrides. Prior to the override keyword this was the only way to ensure you did not accidentally create a new virtual function instead of overriding a parent, and it remains the only way where the policy is enforced in the parent type.
Please note that you cannot instantiate an object with pure virtual methods.
Try to instantiate:
C c;
with VC2015, there is an error as expected:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): error C2259: 'C': cannot instantiate abstract class
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: due to following members:
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(12): note: 'void C::f(void)': is abstract
1>f:\dev\src\consoleapplication1\consoleapplication1.cpp(6): note: see declaration of 'C::f'
To answer your question:
The mechanisms only declares the function to be pure virtual, but there is still the virtual function table and the baseclass. It will avoid you instanciate Baseclass (C), but does not avoid using it:
struct D : public C { virtual void f(); };
void D::f() { printf("Baseclass C::f(): "); C::f(); }
...
D d;
d.f();
The destructor must be defined, even if it is pure virtual. If you don't define the destructor the compiler will generate one.
Edit: you can't leave destructor declared without define, will cause link error.
You can anyway call the body of the function from derived classes.
You can implement the body of a pure virtual function to provide a default behavior, and at the same time you want that the designer of the derived class use that function explicitly.
If I have a hierarchy of C++ classes where the base class has a member function that is declared as virtual, but derived classed do not declare that function as virtual, how far into the class hierarchy does the virtualization carry. For example, given the code is the return value of MyFunc2 well defined?
class A
{
public:
virtual int x() { return 1; }
}
class B : public A
{
public:
int x() { return 2; }
};
class C: public B
{
public:
int x() { return 3; }
};
int MyFunc1(f &A)
{
return f.x();
}
int MyFunc2(f &B)
{
return f.x();
}
int MyFunc3()
{
C c;
return MyFunc1(c);
}
int MyFunc4()
{
C c;
return MyFunc2(c);
}
From similar question here, it would appear that the virtual characteristic is propagated forward to all classes once it is virtual in the base class, but I'm wondering how well defined this is, specifically is B.x() virtual by implication of being derived from A.
Overrides in subclasses are implicitly virtual too. You can specify the virtual keyword again, but it does not make any difference, although it's often considered good practice. It is absolutely "well defined" in the standard.
Starting C++11, you have an even better option: you can tag virtual methods in subclasses with override to ensure they actually override something. This prevent not actually overriding parent methods because of a small prototype difference and will trigger errors if you change the base virtual prototype but forget to adapt the overrides.
Yes, the virtual characteristic is "propagated" (to use your wording) to all derived classes. If derived classes declare and define a member function with the same signature as an inherited virtual function, they override it.
C++11 introduced the final modifier which derived classes can use to prevent their descendents from further-overriding an inherited virtual function. However, the function is still technically virtual (e.g. given a pointer to base, a polymorphic call of p->func() calls the func() corresponding to the actual type of the object) .... it just cannot be overridden.
This question already has answers here:
private inheritance
(6 answers)
Closed 9 years ago.
In C++: assume I have a class X. Is there any difference between private inheritance like this:
class Deriv : private X
{
public:
//constructor etc
void method()
{
usageOfMethodFromX();
}
};
and this:
class Deriv
{
private:
X * m_xinstance;
public:
//constructor etc
void method()
{
m_xinstance->usageOfMethodFromX();
}
};
Is there any difference that does not allow substitute private inheritance with having a member of derived class and vice versa? Is this the same?
Thanks!
There is a subtle difference in case your base class has a virtual function: even if the base class is inherited privately, it can be overridden:
#include <iostream>
class Base {
virtual int do_f() { return 1; }
public:
int f() { return this->do_f(); }
};
class Derived: Base {
int do_f() { return 2; }
public:
int g() { return this->f(); }
};
class Final: public Derived {
int do_f() { return 3; }
};
int main() {
Final final;
std::cout << final.g() << '\n';
}
The above code will print 3 (live example).
Another difference in your code is that the approach allocating memory, well, allocates memory on heap. You can avoid this heap allocation by embedding the object into your derived object.
There is a very significant and clear-cut difference: Consider this X:
class X {
protected:
void doSmth();
};
Only classes inheriting from X will have access to any and all protected members (here X::doSmth()).
Yes.
In the inheritance model, the lifetime of the two objects is intertwined. A number of methods are automatically connected by default (operator=, constructors, destructors) and others may be in the future (operator swap aka :=:, =default other operators like < or ==). On top of this, virtual method overriding and calling can route calls to pointers to your parent interface (which you can provide others, or can be invoked by calling your parent methods) back to you.
If you replace your X * m_xinstance with X m_xinstance things get closer to being the same. Lifetime is now tied, and many (all?) of the hooked up methods are now hooked up similarly. virtual behavior is also very different.
A final difference is that if your base class is empty, the empty base class optimization can occur in one case, but not the member instance. As different objects must have different addresses, a member of your class has a minimum size of 1, while an empty base class can take up zero memory.