I would like to ask a question about programming style in this case of derived class:
class A
{
public:
virtual foo1()=0;
}
class B: public A
{
public:
virtual foo1();
virtual foo2();
}
class C: public A
{
public:
virtual foo1();
}
int main() {
B mB();
C mC();
mB.foo2() //OK!
mC.foo2() // obviously, it is not correct
return 0;}
Therefore, should a derived class have less or equal public methods than the abstract base class?
If the derived classes require more methods, should these be private?
Derived classes will almost always have more public functions than base classes. This is the point of inheritance: you can define an abstract base class which only outlines the basic behavior of a variable, then derived classes can expand upon this basic behavior for specific cases.
An inherited class is always a specialization of the base class. It implements more specific functions (and usually more functions all together). In you're example, you're expecting two different specializations to behave the same way outside of the behavior defined by the base class. (foo2 is not defined in A). That's where the problem lies. If you need to define common behavior outside of A, the solution would be to create an intermediate class.
class Intermediate : public A
{
public:
virtual foo1()=0;
virtual foo2()=0;
}
class B: public Intermediate
{
public:
virtual foo1();
virtual foo2();
}
Now any class which can implement foo2 should extend Intermediate, and any function which requires functionality foo2 should ask for a variable with at least type Intermediate.
There is nothing wrong with this class structure. There is nothing wrong with a derived class having more methods than the parent class-- it's quite commonplace. The line mC.foo2(); is just wrong, and that is not the fault of the classes.
A derived class must at least implement ALL abstract methods from the base class. This is the minimum. If you do add other methods, members or whatever is up to you.
But it would be not very smart to derive from the class and add nothing, because this is not what inheritance is for (at least IS-A-relationships). If you go for private inheritance it might be different.
In nearly ALL projects I've worked on, we have had baseclasses that have less functionality than the derived class - in extreme cases, the baseclass may even just have nearly no functionality, but the derived class has dozens of functions and a half a dozen member variables.
This is exactly what derived classes are meant to do.
Obviously, you need to KNOW what kind of derived class you have, and only use the derived classes "extra" functions when they are available.
Related
I was going through one of my local libraries and noticed the follwowing:
class Derived : public Base
{
friend class Base; // serves as a factory
protected:
pthread_spinlock_t allocLock;
bool isSafe{ true };
Derived();
char *funcA() override;
public:
void funcB( bool _in ) override;
virtual ~Derived();
};
I am not able to understand if Base has been inherited then why it has been made a friend of Derived. Also how the comment serves as a factory make sense here?
If it were to access Base function, :: operator would have been sufficient.
Is it more related to Design approach?
Making the base class a friend gives the base class access to the private members of the derived class. It is hard to tell what the reason for this is here without seeing the definition of class Base. The comment seems to indicate that the base class has member functions to create objects of the derived classes.
Generally, this is bad design. It is a bad thing when the base class knows about its derived classes at all, and it is even worse when it has access to the derived classes' private members. The dependencies should only go one way: derived classes depend on the base class, not the other way around. In other words, a change in the derived class should not break the base class.
If you need a factory, the right way to do this is to put the creation logic into a separate factory class, not into the base class.
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?.
I searched for this, but I feel I'm not finding the answer I'm after. So, simple version and hopefully someone can just say "here's how" and I'll be on my way :)
Essentially I want this:
class BaseObject
{
public:
BaseObject();
~BaseObject();
virtual bool FunctionX() =0;
virtual bool FunctionY() =0;
};
class ObjectA : BaseObject
{
public:
ObjectA();
~ObjectA();
bool FunctionX();
bool FunctionY();
bool FunctionZ();
};
.. same for ObjectB as above ..
...
vector<BaseObject*> myList;
ObjectA a;
ObjectB b;
myList.push_back((BaseObject*)&a);
myList.push_back((BaseObject*)&b);
myList.back()->FunctionX();
I know the code above is wrong, I'm just trying to get the overall concept over.
What I need:
A base class that defines functions that MUST be present in classes that inherit from it.
The ability to store the classes that inherit from it all in the same vector (cast as the base class).
The vector to know it can call the base classes defined functions.
The classes to be able to have their own, additional functions that the vector/base class do not need to be aware of.
I just noticed, you're deriving privately. BaseObject is a private base class of ObjectA. When you omit the inheritance specifier, you get private inheritance by default. Change the ObjectA declaration to
class ObjectA : public BaseObject...
Otherwise, code outside of the ObjectA scope is not allowed to know that ObjectA is-a BaseObject.
Your code is almost right. It misses the virtual for BaseObject's destructor, however, which will invoke undefined behaviour (e.g. crashes) in any typical usage scenario. This is the correct declaration:
virtual ~BaseObject();
Another thing you should consider is making your public functions non-virtual and your virtual functions private, with the public functions delegating to the private ones (called Non-Virtual Interface Idiom by Herb Sutter).
A few more things:
A base class that defines functions that MUST be present in classes
that inherit from it.
You won't be able to achieve this, at least in the literal sense, by any normal means. A class can derive from your abstract class but remain itself abstract by not defining your pure virtual functions.
The ability to store the classes that inherit from it all in the same
vector
Mind the difference between "class" and "object". A vector doesn't store classes but objects. In C++, classes cannot be used as objects (which is different in Java, for example). To "store classes" implies something like type lists in advanced template metaprogramming, a technique not related at all to your problem.
(cast as the base class).
You do not need to cast from subclass to base class.
I've a question regarding a concept. First, I'm a mechanical engineer and not a programmer, thus I have some C++ knowledge but not much experience. I use the finite element method (FEM) to solve partial differential equations.
I have a base class Solver and two child linSolver, for linear FEM, and nlinSolver for non-linear FEM. The members and methods that both children share are in the base class. The base class members are all protected. Thus using inheritance makes the child classes "easy to use", like there weren't any inheritance or other boundaries. The base class itself, Solver, is incomplete, meaning only the children are of any use to me.
The concept works actually pretty good - but I think that having an unusable class is a bad design. In addition I read that protected inheritance is not preferred and should be avoided if possible. I think the last point don't really apply to my specific use, since I will never use it allow and any attempt to do so will fail (since it is incomplete).
The questions are:
Is it common to use inheritance to reduce double code even if the base class will be unusable?
What are alternatives or better solutions to such a problem?
Is protected inheritance really bad?
Thank you for your time.
Dnaiel
Having "unusable" base classes is actually very common. You can have the base class to define a common interface usable by the classes that inherits the base-class. And if you declare those interface-functions virtual you can use e.g. references or pointers to the base-class and the correct function in the inherited class object will be called.
Like this:
class Base
{
public:
virtual ~Base() {}
virtual void someFunction() = 0; // Declares an abstract function
};
class ChildA : public Base
{
public:
void someFunction() { /* implementation here */ }
};
class ChildB : public Base
{
public:
void someFunction() { /* other implementation here */ }
};
With the above classes, you can do
Base* ptr1 = new ChildA;
Base* ptr2 = new ChildB;
ptr1->someFunction(); // Calls `ChildA::someFunction`
ptr2->someFunction(); // Calls `ChildB::someFunction`
However this will not work:
Base baseObject; // Compilation error! Base class is "unusable" by itself
While the (working) example above is simple, think about what you could do when passing the pointers to a function. Instead of having two overloaded functions each taking the actual class, you can have a single function which takes a pointer to the base class, and the compiler and runtime-system will make sure that the correct (virtual) functions are called:
void aGlobalFunction(Base* ptr)
{
// Will call either `ChildA::someFunction` or `ChildB::someFunction`
// depending on which pointer is passed as argument
ptr->someFunction();
}
...
aGlobalFunction(ptr1);
aGlobalFunction(ptr2);
Even though the base-class is "unusable" directly, it still provides some functionality that is part of the core of how C++ can be (and is) used.
Of course, the base class doesn't have to be all interface, it can contain other common (protected) helper or utility functions that can be used from all classes that inherits the base class. Remember that inheritance is a "is-a" relationship between classes. If you have two different classes that both "is-a" something, then using inheritance is probably a very good solution.
You should check the concept of Abstract class.
It's designed to provide base class that cannot be instantiated.
To do so you provide at least one method in the base class like this
virtual void f()=0;
Each child have to override the f function (or any pure virtual function from the base class) in order to be instantiable.
Don't think of the BaseClass as a class in its own right, but as an interface contract and some implementation help. Therefore, it should be abstract, if neccessary by declaring the dtor pure virtual but providing an implementation anyway. Some OO purists may frown upon any non-private element, but purity is not a good target.
I'm reading about inheritance and I have a major issue that I haven't been able to solve for hours:
Given a class Bar is a class with virtual functions,
class Bar
{
virtual void Cook();
};
What is the different between:
class Foo : public Bar
{
virtual void Cook();
};
and
class Foo : public virtual Bar
{
virtual void Cook();
};
? Hours of Googling and reading came up with lots of information about its uses, but none actually tell me what the difference between the two are, and just confuse me more.
Functionality wise there is not much difference between the 2 versions. With the case of virtual inheritance, every implementation generally adds a (vptr like) pointer (same as in the case of virtual functions). Which helps to avoid multiple base class copies generated due to multiple inheritance (the diamond inheritance problem)
Also, virtual inheritance delegates the right to call the constructor of its base class. For example,
class Bar;
class Foo : public virtual Bar
class Other : public Foo // <--- one more level child class
So, now Bar::Bar() will be called directly from Other::Other() and also will be placed at the first place among other base classes.
This delegation feature helps in implementing a final class (in Java) functionality in C++03:
class Final {
Final() {}
friend class LastClass;
};
class LastClass : virtual Final { // <--- 'LastClass' is not derivable
...
};
class Child : public LastClass { // <--- not possible to have object of 'Child'
};
Virtual inheritance is only relevant if classes are to inherit from
Foo. If I define the following:
class B {};
class L : virtual public B {};
class R : virtual public B {};
class D : public L, public R {};
Then the final object will only contain one copy of B, shared by both
L and R. Without the virtual, an object of type D would contain
two copies of B, one in L, and one in R.
There is some argument that all inheritance should be virtual (because
in the cases where it makes a difference, that is what you want most of
the time). In practice, however, virtual inheritance is expensive, and
in most cases, not necessary: in a well designed system, most
inheritance will simply be of a concrete class inheriting from one or
more "interfaces"; such a concrete class is usually not designed to be
derived from itself, so there is no problem. But there are important
exceptions: if, for example, you define an interface, and then
extensions to the interface, the extensions should inherit virtually
from the base interface, since a concrete implementation could want to
implement several extensions. Or if you are designing mixins, where
certain classes only implement part of the interface, and the final
class inherits from several of these classes (one per part of the
interface). In the end, the criteron as to whether to inherit virtually
or not isn't too difficult:
if the inheritance isn't public, it probably shouldn't be virtual
(I've never seen an exception), otherwise
if the class is not designed to be a base class, there's no need for
virtual inheritance, otherwise
the inheritance should be virtual.
There are a few exceptions, but the above rules err on the side of
safety; it's usually "correct" to inherit virtually even in cases where
the virtual inheritance isn't necessary.
One final point: a virtual base must always be initialized by the most
derived class, not the class that directly inherits (and declares that
the inheritance is virtual). In practice, however, this is a non-issue.
If you look at the cases where virtual inheritance makes sense, it is
always a case of inheriting from an interface, which will contain no
data, and thus have (only) a default constructor. If you find yourself
inheriting virtually from classes with constructors which take
arguments, it's time to ask some serious questions about the design.
In this case, no difference. Virtual inheritance is related to sharing superclass subobjects instances by derived classes
struct A
{
int a;
};
struct B : public virtual A
{
int b;
}
struct C : public virtual A
{
int c;
};
struct D : public B, public C
{
};
There's a single copy of the member variable a in the instance of D; If A was not a virtual base class, there would be two A subobjects in instance of D.
Virtual function is a function that will probably have different implementation in derived class (although it's not a must).
In your last example is virtual inheritance. Imagine a case where you have two classes (A and B) derived from a base class (let's call it 'Base'). Now imagine a third class C derived from A and B. Without virtual inheritance, the C would contain two copies of 'Base'. That could lead to ambiguity while compiling. The important thing in virtual inheritance is that the parameters for the 'Base' class constructor (if any) MUST be provided in the class C, because such calls from A and B will be ignored.