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) {}
};
Related
There are a lot of questions about this topic, but however, I didn't find the solution for my following question:
I have the following classes:
1) The pure virtual class
class Employee {
private:
vector<Employee> vec_employee;
public:
Employee() {};
virtual ~Employee() {};
virtual void set_vec_subordinate(vector<Employee> vec_employee) = 0;
};
2) A derived class
class Worker : Employee{ private: public: };
3) Another derived class which should override the pure virtual method from Employee
class Manager : Employee {
private:
public:
inline void set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); };
};
What I try to achieve is to override the pure virtual method but use a "different" parameter. So still new to C++ but I think there should be a way to do so, especially because the other parameter is from type Worker which is a derived class from Employee.
There is no way to do exactly what you plan to do (and there is good reason for that).
Your code is also inherently broken, as you use the type vector<Employee>, which requires objects of type Employee - which cannot exist, as Employee is an abstract class. You may wish to use a vector of a reference type, e.g., vector<shared_ptr<Employee>> instead. (The rest of this answer glosses over this fact to make it more readable.)
Note also that void Manager::set_vec_subordinate(vector<Worker> vec_employee) override { this->set_vec_subordinate(vec_employee); }; would cause an infinite loop (probably resulting in a stack overflow) when called, as it will just keep calling itself.
The class Employee has a contract with its users, that says the following code must be valid (assuming given get_boss and get_workers functions):
Employee& boss = get_boss();
vector<Employee> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec);
Now, this might not make any semantic sense for your application, but the syntax of the programming language means that this must be possible. Some programming languages (not C++!) allow covariant calls similar to this:
Employee& boss = get_boss();
vector<Worker> subordinate_vec = get_workers();
boss.set_vec_subordinate(subordinate_vec); // Invalid C++: `vector<Worker` cannot be converted to `vector<Employee>` implicitly
While it is indeed possible to create a container in C++ that behaves in a way so that this use is possible, it is easier to deal with it is by making the set_vec_subordinate function a template that requires an arbitrary container of objects that are implicitly convertible or derived from Employee - and then just converting the objects during the copy operation (since the vector is not movable in that case anyway).
The second idea is that it should be possible to change the signature of a function when overriding it. This is kind of possible in C++ by implementing the base case (which needs to be binary compatible with - a.k.a. equal to - the signature of the Employee version, as it will be called for that case as well) and then adding additional overloads. For example, you could do something along the lines of:
class Manager : Employee {
private:
public:
inline void set_vec_subordinate(vector<Employee> vec_employee) override { this->vec_employee = std::move(vec_employee); };
inline void set_vec_subordinate(vector<Worker> const& vec_worker) {
vec_employee = std::vector<Employee>(vec_worker.begin(), vec_worker.end()); // copy convert all elements
};
};
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.
I am confused about the concepts of inheritance and polymorphism. I mean, what is the difference between code re-usability and function overriding? Is it impossible to reuse parent class function using inheritance concept or else is it impossible to override parent class variables using Polymorphism. There seems little difference for me.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
My doubt is about the difference between the code reuse and function overriding.
Lets start with your example.
class A
{
public:
int a;
virtual void get()
{
cout<<"welcome";
}
};
class B:public A
{
a =a+1; //why it is called code reuse
void get() //why it is called overriding
{
cout<<"hi";
}
};
Inheritance: Here you are deriving class B from class A, this means that you can access all of its public variables and method.
a = a + 1
Here you are using variable a of class A, you are reusing the variable a in class B thereby achieving code reusability.
Polymorphism deals with how a program invokes a method depending on the things it has to perform: in your example you are overriding the method get() of class A with method get() of class B. So when you create an instance of Class B and call method get you'll get 'hi' in the console not 'welcome'
Function inheritance allows for abstraction of behaviour from a "more concrete" derived class(es) to a "more abstract" base class. (This is analogous to factoring in basic math and algebra.) In this context, more abstract simply means that less details are specified. It is expected that derived classes will extend (or add to) what is specified in the base class. For example:
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
private:
int m_commonProperty;
};
class Subtype1 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
char getProperty(void) const { return m_specificProperty1; }
private:
char m_specificProperty1;
};
class Subtype2 : public CommonBase
{
// Add more specific stuff in addition to inherited stuff here...
public:
float getProperty(void) const { return m_specificProperty2; }
private:
float m_specificProperty2;
};
Note that in the above example, getCommonProperty() and setCommonProperty(int) are inherited from the CommonBase class, and can be used in instances of objects of type Subtype1 and Subtype2. So we have inheritance here, but we don't really have polymorphism yet (as will be explained below).
You may or may not want to instantiate objects of the base class, but you can still use it to collect/specify behaviour (methods) and properties (fields) that all derived classes will inherit. So with respect to code reuse, if you have more than one type of derived class that shares some common behaviour, you can specify that behaviour only once in the base class and then "reuse" that in all derived classes without having to copy it. For example, in the above code, the specifications of getCommmonProperty() and setCommonProperty(int) can be said to be reused by each Subtype# class because the methods do not need to be rewritten for each.
Polymorphism is related, but it implies more. It basically means that you can treat objects that happen to be from different classes the same way because they all happen to be derived from (extend) a common base class. For this to be really useful, the language should support virtual inheritance. That means that the function signatures can be the same across multiple derived classes (i.e., the signature is part of the common, abstract base class), but will do different things depending on specific type of object.
So modifying the above example to add to CommonBase (but keeping Subtype1 and Subtype2 the same as before):
class CommonBase
{
public:
int getCommonProperty(void) const { return m_commonProperty; }
void setCommonProperty(int value) { m_commonProperty = value; }
virtual void doSomething(void) = 0;
virtual ~CommonBase() { }
private:
int m_commonProperty;
};
Note that doSomething() is declared here as a pure virtual function in CommonBase (which means that you can never instantiate a CommonBase object directly -- it didn't have to be this way, I just did that to keep things simple). But now, if you have a pointer to a CommonBase object, which can be either a Subtype1 or a Subtype2, you can call doSomething() on it. This will do something different depending on the type of the object. This is polymorphism.
void foo(void)
{
CommonBase * pCB = new Subtype1;
pCB->doSomething();
pCB = new Subtype2;
pCB->doSomething(); // Does something different...
}
In terms of the code sample you provided in the question, the reason get() is called "overriding" is because the behaviour specified in the B::get() version of the method takes precedence over ("overrides") the behaviour specified in the A::get() version of the method if you call get() on an instance of a B object (even if you do it via an A*, because the method was declared virtual in class A).
Finally, your other comment/question about "code reuse" there doesn't quite work as you specified it (since it's not in a method), but I hope it will be clear if you refer to what I wrote above. When you are inheriting behaviour from a common base class and you only have to write the code for that behaviour once (in the base class) and then all derived classes can use it, then that can be considered a type of "code reuse".
You can have parametric polymorphism without inheritance. In C++, this is implemented using templates. Wiki article:
http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29#Parametric_polymorphism
Suppose I have an abstract base class Base. I want the derived classes to be processed in a different way depending on their types. I could do it like this:
class Base {
public:
virtual void process() const = 0;
};
class DerivedOne : public Base {
public:
virtual void process() const { std::cout << "processed one" << std::endl; }
};
But I'd like to move the logic of processing into separate class so that derived classes were not aware of the way they are processed. I have an idea of how to do it, but I am not sure if it is common or elegant:
enum Type {
TypeOne,
TypeTwo
};
class Base {
public:
virtual Type type() const = 0;
};
class DerivedOne : public Base {
public:
virtual Type type() const { return TypeOne; }
};
class DerivedTwo : public Base {
public:
virtual Type type() const { return TypeTwo; }
};
class Processor {
void process(const Base& b) {
switch(b.type()) {
case TypeOne: std::cout << "processed one" << std::endl; break;
case TypeTwo: std::cout << "processed two" << std::endl; break;
}
}
};
So the questions are:
1) is it ok when virtual method returns some constant representing the type of derived class?
2) is such approach of using switch on the type of object commonly used?
3) are there any other design ideas to separate processing from the object being processed?
That makes no sense.
You're taking virtual dispatch, a feature deliberately created to make polymorphism work without messing up your call site or removing ClassX logic from actually within ClassX ... and trying to undo all its usefulness.
You might as well not bother with polymorphism at all, and simply store your Type as a member variable in a single class.
Quiz Time.
Why do we use polymorphism?
To provide different behavior for similar operations, where the behavior is selected at run-time.
Polymorphism is used to abstract away the implementation of an operation from the provision of that operation. All Base objects for example have a common set of methods. How those methods are implemented depends on the object itself. As a user of the object, we don't care what specific kind of object it is -- only that is is derived from Base and therefore has certian methods on it. We just call the method and let the object handle how it's implemented.
Why would we need to determine at run-time which subclass an object is derived from?
Because only the subclass provides some operation we need.
Designing an interface with a pure virtual method that indicates the actual type of object smells. It's smelly because the only reason why you would need to know the actual type of an object is because the interface doesn't provide some functionality we need, and the only thing that does provide that functionality is the object itself. But this is counter to the point of polymorphism -- to ensure the provision of functionality while leaving the details of that functionality up to the object.
Consider using RTTI's typeid() function rather than creating your own virtual method to return the derived type.
<humor> because you are using a built-in C++ function people will be less likely to argue with you about whether your design is broken. If the C++ standards committee thinks you need the functionality then it's probably legit! </humor>
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.