Say I have an interface class A (class with only pure virtual functions). Also, I have a concrete class B, which holds a weak pointer to A, and calls methods on it.
There is strong coupling between classes A and B. Basically I expect only class B will call methods on class A.
Does it make sense to declare all methods on A, private (pure) virtual and make class B its friend. The classes implementing A, will be free to change the access of the functions they implement as part of inheriting A. It seems appropriate for the use case but I haven't seen it used before.
It makes sense, and it addresses one design issue, but it raises another one (which you might either consider minor or not).
In Sutter and Alexandrescu's C++ Coding Standards there's a guideline 39. Consider making virtual functions nonpublic, and public functions nonvirtual. This makes sense. Say you have
class interface {
public:
virtual void bar();
};
then you realize that all bars have something in common: maybe you want to validate arguments passed to them (if they take arguments), or log calls to all of them. Because of this, the guideline is to split it into
class interface {
public:
void bar() { bar_(); }
protected:
virtual void bar_();
};
I.e., a public non-virtual method calling a non-public virtual one. The public one is the only gateway to the virtual one.
The problem is that this is the only gateway until you introduce friend. Then, you have no control, and the external class can call bar_ directly, circumventing it.
In your case, you could consider the following, therefore:
Say the class to which you want to grant access is foo, and the interface class is interface. Write another class interface_accessor, which will be the gateway:
class foo;
class interface;
class interface_accessor {
private:
static void bar(interface &i);
friend class foo;
};
Note that interface_accessor is a friend of foo.
Now, make interface a friend of interface_accessor, but not of foo:
class interface {
private:
virtual void bar_() {}
friend class interface_accessor;
};
Finally, implement interface_accessor:
void interface_accessor::bar(interface &i) {
i.bar_();
}
Related
Regarding the question "How to publicly inherit from a base class but make some of public methods from the base class private in the derived class?", I have a follow-up question:
I can understand that the C++ standard allows a derived class to relax access restrictions of an inherited method, but I can not think of any legitimate use case where it would make sense to impose access restrictions in the derived class.
From my understanding of the concept of inheritance, if class Derived is public class Base, then anything you can do with Base can also be done with Derived. If one does not want Derived to fulfill the interface of Base, one should not use (public) inheritance in the first place. (Indeed, when I encountered this technique in the wild in ROOT's TH2::Fill(double), is was a clear case of inheritance abuse.)
For virtual methods, access restrictions in Derived are also useless, because any user of Derived can use them by casting a Derived* into a Base*.
So, from my limited C++ newbie point of view, these restrictions are misleading (the programmer of Derived might assume that his virtual now-protected method is not called by anyone else, when in fact it might be) and also confuses [me with regard to] what public inheritance should imply.
Is there some legitimate use case I am missing?
From Herb Sutter, Guru of the Week #18:
Guideline #3: Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.
For detail answer, please read my comment in the code written below:
#include <iostream>
#include <typeinfo>
#include <memory>
struct Ultimate_base {
virtual ~Ultimate_base() {}
void foo() { do_foo(); }
protected:
// Make this method protected, so the derived class of this class
// can invoke this implementation
virtual void do_foo() { std::cout << "Ultimate_base::foo"; }
};
struct Our_derived : Ultimate_base {
private:
// Make this method private, so the derived class of this class
// can't invoke this implementation
void do_foo() {
Ultimate_base::do_foo();
std::cout << " Our_derived::foo";
}
};
struct Derive_from_derive : Our_derived {
private:
void do_foo() {
// You can't call below code
// vvvvvvvvvvvvvvvvvvvvvv
// Our_derived::do_foo();
std::cout << " Derive_from_derive::foo";
}
};
// This class is marked final by making its destructor private
// of course, from C++11, you have new keyword final
struct Derive_with_private_dtor : Ultimate_base {
private:
~Derive_with_private_dtor() {}
};
// You can't have below class because its destructor needs to invoke
// its direct base class destructor
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
/*
struct Derive_from_private_dtor : Derive_with_private_dtor {
};
*/
int main() {
std::unique_ptr<Ultimate_base> p = std::make_unique<Our_derived>();
p->foo();
p = std::make_unique<Derive_from_derive>();
p->foo();
p.reset(new Derive_with_private_dtor);
}
From my understanding of the concept of inheritance, if class Derived is public class Base, then anything you can do with Base can also be done with Derived.
This isn't really the concept of inheritance; this is the concept of polymorphism. In particular, this is a statement of the Liskov Substitution Principle. But inheritance can be used for various things in C++ beyond just polymorphism. In fact, anytime your base class has non-virtual methods or data members, you are using it to inject implementation or state into derived classes, not only for polymorphism. If the base class has no virtual methods and no virtual destructor, then the class shouldn't (can't) be used polymorphically. You may use a base class where neither will the base class ever be instantiated, nor will you ever use a pointer to a base. Here's an example:
template <class T>
struct Foo {
T double_this() { return 2 * static_cast<T&>(*this).data; }
T halve_this() { return 0.5 * static_cast<T&>(*this).data; }
};
What does this weird class do? Well, it can be used to inject some interface into any class with a data member called data (and an appropriate constructor):
struct Bar : Foo<Bar> {
Bar(double x) : data(x) {}
double data;
};
Now Bar has methods double and halve. This pattern is called Curiously Recurring Template Pattern (CRTP). Note that we're never going to instantiate Foo<Bar> or have a pointer to it. We just use the interface it provides, non polymorphically.
Now, suppose someone wants to use Foo, but only wants double in their interface but not halve. In this case, it's completely valid to make halve private in the derived. After all, the derived class is just some particular, non polymorphic type, that does not need to conform to any interface other than what the author wants/documents.
Note that when using CRTP, the base class will typically provide public functions, and you'll typically inherit publicly. The entire advantage of CRTP in this use case is that you can inject interface directly; if you were going to make the methods private or inherit privately you'd be better off make Foo<Bar> a member of Bar instead. So it would be more common to make something public into something private, rather than the reverse, in this particular situation.
I am trying to complete some school homework, and I've just noticed there might be a problem caused by reusing a function from a base class in a multiply inherited derived class.
Let's say I have these classes:
class A
class B: public A
class C: public A
class D: public B, public C
Each class has this method:
virtual void read(ifstream& in);
In class B and in class C, the read() function is also calling class A::read():
void B::read(ifstream& in)
{
A::read(in);
/* read method of B*/
}
void C::read(ifstream& in)
{
A::read(in);
/* read method of C*/
}
Now, the problem is, that when I want to make a read() function for class D, I'm actually calling A::read() twice:
void D::read(ifstream& in)
{
B::read(in);
C::read(in);
/* read method of D*/
}
I know I can use the option of using the A::read() only in one class (B or C), but let's say I need to use it in both classes.
This is an example of why multiple inheritance, especially from a common ancestor, is discouraged. Not because it's always bad - though it often is!- but more because it's usually difficult. If you can find an alternative, that's often preferable. Not necessarily. I'm sure you'll ponder this and decide if it's the best design. But for now, we're here to look at ways to avoid repeating A::read() and other pitfalls.
I start with an analogy to the famous Dreaded Diamond of Doom - not anywhere near as dread-worthy as legend suggests, but worth bearing in mind. It's illustrative that when working around the 'duplicated base members' problem created by such a diamond-shape inheritance hierarchy, by using virtual inheritance - the derived class now becomes fully responsible for calling all constructors of all of its virtual bases. Constructor calls don't chain upwards like normal, and data member initialisation is weird. Google it!
N.B. You should use virtual inheritance if the top class of your diamond-shaped hierarchy has any data members, to avoid duplicating/introducing ambiguity for them, too. That's what it's for. But back to the main topic where I use it as an analogy to functions (which don't strictly require it).
The idea is to take inspiration from virtual inheritance's requirement for the final class to manually call virtual bases' constructors, by handling derived classes' read() behaviours the same way: Avoid repeated calls by making each of your derived classes' public-facing read() methods fully responsible for calling all base ones. This also gives you fine control over not only which of the bases' methods are called - but also of their order.
How? We can factor out the real work of each derived read() to protected 'implementation' functions in each class, and provide public overridden 'wrapper functions' in each final class. The wrapper functions will then be responsible for calling their respective class's impl and that of any required bases, in whichever order you want:
class A {
protected:
void read_impl(ifstream &in) { /* A-specific stuff */ }
public:
virtual void read(ifstream &in)
{
read_impl(in);
}
};
class B: public A { // N.B. virtual public if A has data members!
protected:
void read_impl(ifstream &in) { /* B-specific stuff */ }
public:
virtual void read(ifstream &in)
{
A::read_impl(in);
read_impl(in); // B
}
};
class C: public A {
protected:
void read_impl(ifstream &in) { /* C-specific stuff */ }
public:
virtual void read(ifstream &in)
{
A::read_impl(in);
read_impl(in); // CMy
}
};
class D: public B, public C {
protected:
void read_impl(ifstream &in) { /* D-specific stuff */ }
public:
virtual void read(ifstream &in)
{
A::read_impl(in);
B::read_impl(in); // avoids calling A again from B
C::read_impl(in); // ditto from C
read_impl(in); // D
}
};
With this, you gain complete control over what base stuff each final class dones, and when, without unwanted repeated calls. In terms of DRY, impl functions mean no repetition of behavioural code is done for intermediate classes: the writing in each derived read() is all useful declarative information about how they orchestrate bases' behaviours. You can also add extra stuff between, etc.
A very non-generic way to fix this issue is with booleans, just a switch for each class (B && C) to state if I should call my super class's function.
Another way to fix it is just not to call A's function in B or C.
I have following dilemma:
I have a full abstract class. Each inheriting class will need 3 same parameters. Each of them will additionally need other specific parameters.
I could:
1) implement a common constructor for initializing 3 common parameters in my base class, but then I have to make non-abstract getters for corresponding fields (they are private).
OR
2) leave my base class abstract and implement constructors in inherited classes, but then I have to make it in each class fields for common parameters.
Which is a better approach? I don't want to use protected members.
An abstract class is one who has at least one pure virtual (or, as you call it, abstract) function. Having non-abstract, non-virtual functions does not change the fact that your class is abstract as long as it has at least one pure virtual function. Go for having the common functionality in your base class, even if it is abstract.
One way to avoid code duplication without polluting your abstract interface with data members, is by introducing an additional level of inheritance:
// Only pure virtual functions here
class Interface {
public:
virtual void foo() = 0;
};
// Things shared between implementations
class AbstractBase : public Interface {
};
class ImplementationA : public AbstractBase {
};
class ImplementationB : public AbstractBase {
};
If your class looks like this, a pure abstract class:
class IFoo {
public:
virtual void doThings() = 0;
}
class Foo {
public:
Foo(std::string str);
void doThings() override;
}
The value your inheritance has is to provide you with the oppurtunity to subsitute Foo with another at runtime, but hiding concrete implementations behind interfaces. You can't use that advantage with Constructors, there's no such thing as a virtual constructor (that's why things like the Abstract Factory Pattern exist). All your implementations of Foo take a std::string and all your implementations of doThings use that string? Great, but that's a coincidence not a contract and doesn't belong in IFoo.
Lets talk about if you've created concrete implementations in IFoo, so that it's a abstract class and not a pure abstract class (IFoo would be a bad name now btw). (*1) Lets assume using inheritance to share behaviour was the correct choice for you class, which is sometimes true. If the class has fields that need to be initialised create a protected constructor (to be called from every child implementation) and remove/ommit the default one.
class BaseFoo {
private:
std::string _fooo;
protected:
BaseFoo(std::string fooo) : _fooo(fooo) {}
public:
virtual void doThings() = 0;
std::string whatsTheBaseString() { return _fooo;}
}
Above is the way you correctly pass fields needed by a base class from the child constructor. This is a compile time guarantee that a child class will 'remember' to initialize _fooo correctly and avoids exposing the actual member fooo to child classes. Trying to initialize _fooo in all the child constructors directly would be incorrect here.
*1) Quickly, why? Composition may be a better tool here?.
In C++, if I have a class Base which is a private base class of Derived but Base has no virtual functions, would it be cleaner to instead replace having inheritance with encapsulation in class Encapsulate? I imagine the only benefit to inheritance in this case would be that the base class can be accessed directly in the derived class as opposed to through memberVariable. Is one or the other practice considered better, or is it more of a personal style question?
class Base {
public:
void privateWork();
// No virtual member functions here.
};
class Derived : Base {
public:
void doSomething() {
privateWork();
}
};
class Encapsulate {
Base memberVariable;
public:
void doSomething() {
memberVariable.privateWork()
}
};
Remember that inheritance models "Liskov substitution": Foo is a Bar if and only if you can pass a Foo variable to every function expecting a Bar. Private inheritance does not model this. It models composition (Foo is implemented in terms of Bar).
Now, you should pretty much always use the second version, since it is simpler and expresses the intent better: it is less confusing for people who don't know about it.
However, sometimes, private inheritance is handy:
class FooCollection : std::vector<Foo>
{
public:
FooCollection(size_t n) : std::vector<Foo>(n) {};
using std::vector<Foo>::begin;
using std::vector<Foo>::end;
using std::vector<Foo>::operator[];
};
This allows you to reuse some of the functionality of vector without having to forward manually the 2 versions (const + non const) of begin, end, and operator[].
In this case, you don't have polymorphism at all: this is not inheritance, this is composition is disguise; there is no way you can use a FooCollection as a vector. In particular, you don't need a virtual destructor.
If there are no virtual functions, then inheritance should not be used in OO. Note this does not mean that it must not be used, there are a few (limited) cases where you might need to (ab)use inheritance for other purposes than OO.
Consider the following code:
class Base
{
public:
virtual void Foo() {}
};
class Derived : public Base
{
private:
void Foo() {}
};
void func()
{
Base* a = new Derived;
a->Foo(); //fine, calls Derived::Foo()
Derived* b = new Derived;
// b->Foo(); //error
static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}
I've heard two different schools of thought on the matter:
Leave accessibility the same as the base class, since users could use static_cast<Derived*> to gain access anyway.
Make functions as private as possible. If users require a->Foo() but not b->Foo(), then Derived::Foo should be private. It can always be made public if and when that's required.
Is there a reason to prefer one or the other?
Restricting access to a member in a subtype breaks the Liskov substitution principle (the L in SOLID). I would advice against it in general.
Update: It may "work," as in the code compiles and runs and produces the expected output, but if you are hiding a member your intention is probably making the subtype less general than the original. This is what breaks the principle. If instead your intention is to clean up the subtype interface by leaving only what's interesting to the user of the API, go ahead and do it.
Not an answer to your original question, but if we are talking about classes design...
As Alexandrescu and Sutter recommend in their 39th rule, you should prefer using public non-virtual functions and private/protected virtual:
class Base {
public:
void Foo(); // fixed API function
private:
virtual void FooImpl(); // implementation details
};
class Derived {
private:
virtual void FooImpl(); // special implementation
};
This depends on your design, whether you want to access the virtual function with a derived class object or not.
If not then yes, it's always better to make them private or protected.
There is no code execution difference based on access specifier, but the code becomes cleaner.
Once you have restricted the access of the class's virtual function; the reader of that class can be sure that this is not going to be called with any object or pointer of derived class.