My group has code with the following structure
class Base
{
public:
float some_base_function();
};
class Derived : public Base
{
public:
float some_other_function();
float yet_another_function();
};
which is simple enough. The issue is that I'm currently thinking about reimplementing Derived in a few experimental ways. My thinking was to do this:
class IDerived : public Base
{
public:
virtual float some_other_function() = 0;
virtual float yet_another_function() = 0;
};
And then change the old Derived to inherit from IDerived. Is this sort of Concrete --> Abstract --> Concrete inheritance structure even allowed in C++?
To make matters worse, the original Derived class is persistified within the framework, so it must maintain the same structure in memory (which I hoped to achieve by making IDerived abstract). Will the new Derived have the same memory layout?
It's legal, but it doesn't seem like you need that. What's the point of the extra inheritance?
Moreover, Base and Derived don't have any virtual methods, so by adding any you can be 99% sure the memory layout won't be the same.
Yes, that is allowed. But general practice is to avoid concrete base classes of any sort (see e.g. Item 33 of Scott Meyers' More Effective C++).
Attempting to persist complex objects by storing their binary representation is bound to lead to all sorts of problems; I would suggest finding a better mechanism (serialization, etc.).
Related
I am a newbiee in C++.
I have two pure abstract classes (like interfaces), and I derive a Class from these two pure abstracts classes.
In a case, I need to upcast the derived class pointer to one of the base abstract classes.
First of all, is there any limitation on that.
class IBase1
{
virtual ~IBase() = default;
}
class IBase2
{
virtual ~IBase2() = default;
}
class Derived : public IBase, public IBase2
{
}
Derived d;
IBase1* basePtr = dynamic_cast<IBase1*>(&d);
Herein, if I use any other cast, I am not pretty sure but I get invalid pointer from the cast, so I need to use dynamic_cast for upcasting from multiple inheritance, is that right?
When I do that, I get an error "source type is not polymorphic"
My base classes are pure abstract classes so they have at least one virtual methid so it should be ok, right but why I get this error? Is it about the multiple inheritance?
Edit: There are one more layer here.
My Derived Class needs to contain two different type of instances but my instances are really huge variable so as a C developer :), I was planning to use an Union for less memory usage.
The union has only instances of two classes which derived from pure abstract classes. So, I was assuming that the union instance address should also points the offsets of my class instances, but C++ cannot probably know the write member methods address.
class IFile
{
public:
virtual ~IFile() = default;
};
class IDirectory
{
public:
virtual ~IDirectory() = default;
};
class FileSystem1 : public IFile, public IDirectory
{
public:
FileSystem1() { }
virtual ~FileSystem1() final override = default;
private:
Native1APIInstance file;
};
class FileSystem2 : public IFile, public IDirectory
{
public:
FileSystem2() { }
virtual ~FileSystem2() final override = default;
private:
Native2APIInstance file;
};
union FileSystemInstance
{
FileSystem1 fs1;
FileSystem2 fs2;
FileSystemInstance(string path)
{
if (path[0] == '1') // initialise fs1
else if (path[0] == '2') // initialise fs2
}
};
FileSystem fs("<PATH to File System>");
IFile* file = reinterpret_cast<IFile*>(&fs);
Herein, I dont want to interest which instance is initialised. I want to work with only the base class interface. I am wondering is that somehow possible with an Union?
Thanks.
class FileSystem1 : public IFile, public IDirectory
Let's sit back and think about just that much for a moment. That asserts that a FileSystem1 is (or more formally, under any possible circumstances, can be used in place of) either an IFile or an IDirectory.
At least as most people use these terms, that's not how things are at all. As most people use the terms, a File system contains some things, each of which can be either a file or a directory:
class FS_node {
virtual std::string name() const { return name_; }
// ...
virtual ~FS_node = default;
};
class File : public FS_node {
// ...
};
class Directory : public FS_node {
// ...
};
class FileSystem {
std::vector<FS_node *> nodes;
public:
// ...
};
Now, from the sound of things, you have to deal with two entirely separate file systems. There are a number of ways of doing that. One possibility would be to have a base FileSystem class that defines an interface to a file system, then have two derivative classes that implement that interface in terms of two separate APIs at the OS level.
Another possibility would be to implement similar functionality, but instead of using inheritance, you'd specify the API interface class as a template parameter when you instantiate a FileSystem object:
template <class Api>
class FileSystem {
Api api;
public:
FileSystem(Api const &api) : api(api) {}
// FS functions for finding files and such go here,
// each implemented via the `Api` passed as a parameter
};
As to the difference between using templates and inheritance: it's pretty much the same as usual: templates are static, so if (for example) you want code that you can specify at compile time whether to compile for Windows or Linux, templates should work nicely. On the other hand, if you're dealing with something like a single collection of file systems, and that collection might contain a mixture of objects, each representing a different file system, and you want to be able to deal with all of them transparently at run time, then you'll probably need to use an inheritance hierarchy.
But at least to me, it seems fairly likely that your original design with FileSystem derived from both File and Directory classes is almost certainly a pretty serious mistake. We'd probably need to know a bit more about what you're doing to be sure of what approach is really optimal, but that's probably not it.
Ignoring all of that about the design for a moment, and looking at the question of how to convert from pointer to derived to point to base, we really have only two cases that matter a whole lot. If you used public inheritance (as shown in the question), the conversion doesn't require a cast at all:
FileSystem1 foo1;
IFile *fileBase = &foo1; // No problem.
IDirectory *dirBase = &foo1; // Likewise
If you used private derivation, then you've just found an exceptionally rare situation: one where you actually need to use a C-style cast to do the conversion properly:
class Base1 {};
class Base2 {};
// Note: private derivation:
class Derived : Base1, Base2 {};
Derived d;
Base1 *b1 = (Base1 *)&d;
Base2 *b2 = (Base2 *)&d;
For this specific case (converting a derived class to an inaccessible base class) none of the "new" C++ casts can do the job--you must us a C-style cast.
It seems the problem is about Union data structure.
For example, if I use union while the following works;
FileSystem fs;
fs.fs1.Func();
the below does not work
FileSystem fs;
FileSystem1* fs1 = &fs.fs1; (No casting, the same type)
fs1->Func();
I got an exception for the second case, it somehow cannot find the virtual function table (Access violation for vtable; 0xCCCCCCCC). Does not make sense to me.
If I change Union to Class type, the same code works. It must be about the Union itself. I need to study it well, or leave the idea. Thank you all.
In C++, I have several classes inheriting from an abstract super class. Subclasses have a static attribute sharing the same name type but of course have different values. My question is what is the best approach to implement this and what are the pros and cons for each implementation.
PS:
There are some related discussions like here but most don't explain why approach (which works on my machine) 1 below should not be used. Besides, the subclass methods in approach 2 are not static and wwe will have to get an instance to invoke them.
Apporach 1: uinitialized const static in superclass
class Abstract {
public:
const static int type;
};
class C1: public Abstract {
public:
const static int type = 1;
};
class C2 : public Abstract {
public:
const static int type = 2;
};
Approach 2: using virtual functions instead of variables
class Abstract {
public:
virtual int get_type() = 0;
};
class C1: public Abstract {
public:
int get_type() {return 1;}
};
class C2 : public Abstract {
public:
int get_type() {return 2;}
};
Other approaches that I'm not aware of...
EDIT:
As some answers/comments mentioned below, I'm trying to identify actual type at runtime. However I cannot really think of a nicer design.
To make it concrete, let's say Abstract=EduInst for educational institution, C1=Univ, C2=College, etc. I have a std::map<Key, EduInst*> storing all institutions, which are generated at runtime depending on user input. At times I need to operate only on Univs or Colleges. What is a good way to implement this?
First the warnings:
Inheritance describes an "is kind of" relationship with the base class. It only makes sense when you are storing different kinds of objects in the same container, when those kinds of object absolutely share the same interface, and when no special handling is required on any one of the derived classes (i.e. when you, the object's consumer don't need to know its type).
Furthermore, if you only have a few kinds of the same thing, and those kinds of thing can possibly be known at compile time, then it's probably a mistake to use inheritance.
If your inherited object must identify its actual type to a client, this is further evidence that inheritance is the wrong solution - since now you're going to use code to find code, which is a bad idea (it's not testable, and it's liable to go wrong when your program is in a state that you didn't anticipate).
Furthermore, if you have objects that are dissimilar but need to be stored in the same container, then boost::variant is probably the solution you're looking for. You would then use boost::static_visitor to perform operations on the object in the variant. The advantage of this is that is absolutely type-safe and the compiler won't allow you to forget to handle a type.
Having said all that...
approach 1 won't work because if you have the type of the derived class already, you'll always get the base class' type.
approach 2 will work but it's horrid and an indication of a broken design.
You can't have "virtual" static members.
Approach one is for finding out the "type" attribute of a class, the second for finding out the "type" attribute of an instance.
To put it differently: to use the first, you need to know the class; to use the second, you need to know the instance.
It's impossible to write code where you know neither.
Note that approach one can give you unexpected results if you use type inside a function in a base class.
For instance,
class Abstract
{
public:
int get_type() const { return type; }
};
// ...
C1 c;
std::cout << c.get_type();
will output 0, since that is the value of Abstract::type.
A variation of the second approach lets you avoid the virtual function if you sacrifice the space of another member:
class Abstract {
public:
// ...
int get_type() const { return type; }
protected:
Abstract(int t) : type(t) {}
private:
int type;
};
class C1: public Abstract {
public:
C1() : Abstract(1) {}
};
class C2 : public Abstract {
public:
C2() : Abstract(2) {}
};
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 have a base class Base that I declare several polymorphic subclasses of. Some of the base class's functions are pure virtual while others are used directly by the subclass.
(This is all in C++)
So for instance:
class Base
{
protected:
float my_float;
public:
virtual void Function() = 0;
void SetFloat(float value){ my_float = value}
}
class subclass : public Base
{
void Function(){ std::cout<<"Hello, world!"<<std::endl; }
}
class subclass2 : public Base
{
void Function(){ std::cout<<"Hello, mars!"<<std::endl; }
}
So as you can see, the subclasses would rely on the base class for the function that sets "my_float", but would be polymorphic with regards to the other function.
So I'm wondering if this is good practice. If you have an abstract base class, should you make it completely abstract or is it okay to do this sort of hybrid approach?
This is a common practice. In fact, some well-known design patterns rely on this, such as the Template Method Pattern. In a nutshell, this allows you to specify some aspects of the behavior you're describing through your class hierarchy as invariant, while letting other aspects of that behavior vary based on the specific type of instance you are referring to at a given point.
Whether or not it is a good or not depends on your precise use case: does it make sense for you to share the implementation of your float member data storage among all your base classes ? This is a bit hard to answer with the example you posted as the derived classes do not rely on my_float in any way, but there are tons of cases where this makes sense and is a good way to split the responsibilities of your class hierarchy.
Even in cases where it does make sense to share implementation of details across classes, you have several other options, such as using composition to share functionality. Sharing functionality through a base class often allows you to be less verbose compared to sharing this functionality via composition, because it allows you to share both the implementation and the interface. To illustrate, your solution has less duplicated code than this alternative that uses composition:
class DataStorage {
private:
float data_;
public:
DataStorage()
: data_(0.f) {
}
void setFloat(float data) {
data_ = data;
}
};
class NotASubclass1 {
private:
DataStorage data_;
public:
void SetFloat(float value){ data_.setFloat(value); }
...
}
class NotASubclass2 {
private:
DataStorage data_;
public:
void SetFloat(float value){ data_.setFloat(value); }
...
}
Being able to have some functions non-virtual has certain benefits, many strongly related:
you can modify them, knowing invocations via a Base*/Base& will use your modified code regardless of what actual derived type the Base* points to
for example, you can collect performance measurements for all Base*/&s, regardless of their derivation
the Non-Virtual Interface (NVI) approach aims for "best of both worlds" - non-virtual functions call non-public virtual functions, giving you a single place to intercept calls via a Base*/& in Base as well as customisability
calls to the non-virtual functions will likely be faster - if inline, up to around an order of magnitude faster for trivial functions like get/set for few-byte fields
you can ensure invariants for all objects derived from Base, selectively encapsulating some private data and the functions that affect it (the final keyword introduced in C++11 lets you do this further down the hierarchy)
having data/functionality "finalised" in the Base class aids understanding and reasoning about class behaviour, and the factoring makes for more concise code overall, but necessarily at the cost of frustrating flexibility and unforeseen reuse - tune to taste
I am quite new to real use of templates, so I have the following design question.
I am designing classes Bunch2d and Bunch4d that derive from a abstract base class Bunch:
class Bunch {virtual void create()=0;};
class Bunch2d : public Bunch {void create();};
class Bunch4d : public Bunch {void create();};
The class Bunch will contain a container, a deque or a vector (see this question: Choice of the most performant container (array)) of Particle's:
typedef Blitz::TinyVector<double,DIMENSIONS> Particle;
You therefore see my question: Bunch has to contain this container, because the "base" operations on my bunch are "dimension independant" (such a "size of the container", "clear container", etc.), so I think that the container belongs to the base class ("Bunch 'has a' container).
But this container has to know the dimensions (2 or 4) of the derived class.
So my idea would be to use a templated base class to give the typedef the correct dimension of the container:
enum Dimensions {TwoDimensions = 2, FourDimensions = 4, SixDimensions = 6};
template<Dimensions D> class Bunch
{
protected:
typedef Blitz::TinyVector<double,D> Particle;
std::deque<Particle> particles_store;
public:
virtual void create() = 0;
virtual ~Bunch();
};
class Bunch2d : public Bunch<TwoDimensions>
{
public:
~Bunch2d();
void create();
};
class Bunch4d : public Bunch<FourDimensions>
{
public:
~Bunch4d();
void create();
};
Can you give me your opinion on this design ? Would it be correct use of templates ? What about the validity of the OO concepts ? With a templated base class ?
Thanks for you help/answer/opinion.
There is one single note: different template instances (ie template classes with different types in the parameters) are of different types, and therefore are NOT a single base class.
If you need polymorphism, you will need to add a layer in your design:
class Bunch
{
public:
virtual void create() = 0;
virtual ~Bunch();
};
template <Dimensions D>
class TBunch: public Bunch
{
private:
typedef Blitz::TinyVector<double,D> Particle;
std::deque<Particle> mParticles;
};
class Bunch2d : public TBunch<TwoDimensions>
{
public:
~Bunch2d();
void create();
};
On another note: protected should be banned for attributes.
The issue is one of coupling, since protected exposes the attributes / methods to an unknown number of classes, it's no different than public in that it's impossible to reliably state how many methods will be affected by a change of implementation.
For methods, it's acceptable, because methods can be kept backward compatible (sometimes at the cost of some tricks / etc... but still).
For attributes, it's just unacceptable because an attribute is an implementation detail, not an interface, and a change cannot be made backward compatible.
Therefore I urge you not to EVER use protected for an attribute. In this particular case, it would be a good idea to factor the accesses to mParticles in the template class, without exposing the underlying implementation.
Small hint: if you cannot switch between deque and vector without breaking something beyond the class that holds them, then you have a design issue.
You'd then loose the ability to have a pointer of Bunch class pointing to either Bunch2d or Bunch4d objects at runtime, and manipulate those objects polymorphically through that pointer. If it's important to you not to loose that, don't make the base class templated. Otherwise there is no point in having virtual functions and abstract base class here at all, so then I'd recommend going just with the template.
For a start, Bunch<TwoDimensions> and Bunch<FourDimensions> are completely unrelated classes, so far as inheritance is concerned. Therefore, Bunch2d and Bunch4d have no common base class!
If this is going to be a problem for you, you'll have to do away with the templating, and have DIMENSIONS parameterised at run-time.