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.
Related
I have abstract base class and an empty struct that should be used inside this class
//base.hpp
class Base {
public:
virtual void do_something(const char* arr) {
h = reinterpret_cast<Header*>(arr); //What happens here in the derived class? I would want it to cast it to the respective derived struct
h->val = 10 //these are some common functionalities which I want to include in the base class
}
private:
Header *h;
}
//header.hpp
struct Header {
}
Both the class and struct are inherited
//derivedA.h
class DerivedA : public Base {
...
//this class should refer to HeaderA
}
//header.hpp
struct HeaderA : public Header{
int val;
bool is_it;
}
Similarly there's another derived class DerivedB and it's associated HeaderB.
How can I make the derived classes refer to its respective derived structs?
One of the reasons I have an empty base struct even though they have few common members is that I am using reinterpret_cast. The common members in the incoming buffer are arranged differently. But it is useful to define common functionalities in the base class. What am I missing here? How can I make this work?
0) using reinterpret_cast on a char* is a Really Bad Idea. Change your base constructor to take a Header pointer. Or don't since they don't share anything, there's no real reason to to use inheritance here.
Maybe you're leaving out a bunch of stuff in the base Header for clarity's sake, I dunno. But as written, you don't need the base header pointer in the first place.
1) Make HeaderA inherit from Header.
2) DerivedA's constructor takes a HeaderA* parameter, which is then passed to the base class's Header*-based constructor.
3) DerivedA keeps a separate copy of what it was passed in, with the correct type.
So something like
class Base {
public:
virtual ~Base() {} // virtual base destructor! Very important.
Base(Header* foo)
: header(foo) {
}
private:
Header* header;
...
};
// at the very least, you probably want a virtual destructor here too
struct Header {
virtual ~Header() {}
};
struct HeaderA : public Header {
...
};
class DerivedA : public Base {
public:
DerivedA(HeaderA* header) :
: Base(header)
, headerA(header)
{
...
}
private:
HeaderA* headerA;
};
Note that the ownership of HeaderA isn't addressed here At All. You might want to use a std::unique_ptr<Header> in the base class, and let RAII handle it for you everywhere else... rather than using references, like I have in the above code. Then at least there'd be some point to having it in the base class even if the header was completely empty.
Back to that cast from char* to Header*. I presume you're writing the header out with memcpy() or something like it either to a file, or a packet or some such, in an effort to be efficient.
Don't.
In both AAA MMORPG code bases I've worked on, each field of each struct was written out explicitly (to packets or files). It may have worked like an overly verbose memcpy() in some cases, but we made the effort, because the safety was Worth The Extra Effort. If you continue to do things the way you are, everything in your header has to be Right There.
no pointers
strings have to be fixed size arrays, arrays that will be mostly empty most of the time, because they're sized for your worst case scenario.
object pointers have to be replaced with object IDs, and that the object IDs have to be consistent between when they were written, and when they were read. And those IDs have to be stored in the struct, which means looking them up every time you have to use them.
You're locked into either "big endian" or "little endian" at write time, and heaven help you if your write "endian-ness" is different from your read "endian-ness". ("What the hell are big endian and little endian?" Google it. Right now. Seriously.)
By writing out fields individually you can do things like
write everything out in a particular endian-ness.
convert object pointers to object IDs.
write out a length and then the correct number of characters/bytes rather than a fixed/mostly-empty number of bytes.
encrypt field values (MMOs can't trust the data packets not to be sniffed so players can cheat)
change field order (it's fun to scramble your packets' field order and watch the hackers crash when they connect the first time, at which point you know which accounts to flag for Further Investigation. Yes, this is one of several reasons why your old version of some client won't work with the new version of the corresponding server.)
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 want to specify an interface which requires an abstract class to have a certain type as a member variable.
I'll try to replicate the situation here:
class Blob {
int data[32];
};
class Worker {
string name;
abstract void workOn(Blob&) = 0;
}
class Abstract {
vector<shared_ptr<W>> workerList;
Blob allTheStuff;
abstract void somethingElse() = 0;
void doAllTheWork() {
for (w : workerList) {
w->workOn(allTheStuff);
}
}
};
class B_Blob : public Blob {
int moreData[4096];
};
class BulbasaurTrainingCamp : public Abstract {
B_Blob allTheStuff;
void somethingElse() {} // implemented
// this class will accept Bulbasaurs into workerList
};
class Bulbasaur : Worker {
Bulbasaur(): name("Fushigidane") {}
void workOn(Blob& b) {
// bulbasaurs cover *all* their workspace with crap
for (int i=0; i<sizeof(b.data[0])/sizeof(b.data); ++i) {
b.data[i] = *((int*)&("crap"));
}
for (i=0; i<sizeof(b.moreData[0])/sizeof(b.moreData); ++i) {
b.moreData[i] = *((int*)&("crap"));
}
}
Here, the abstract bas class has a Blob, but the instance of BulbasaurTrainingCamp has a derived B_Blob. It appears that since I gave it the same name, the compiler accepts it.
Is there a name for this? What I want to know is what the behavior is when I do this. Have I overridden the Blob with the B_Blob?
I am basically not sure about whether there is an inaccessible base Blob instance hanging around inside of BulbasaurTrainingCamp. My expectation is that each Bulbasaur will write 16512 (not 16384) bytes of crap across the two member variables of B_Blob. I am hoping that C++ will actually do what appears to be the sensible thing. It's a case of, "it compiles so I think I should be happy, but I'm still not totally sure it's doing what I think it should be doing".
#include<iostream>
#include<vector>
using namespace std;
int main()
{
class base
{
public:
int sameName;
base(int x):sameName(x){}
};
class derived : public base
{
public:
int diffName;
int sameName;
derived(int x,int i,int j):base(x),diffName(i),sameName(j){}
};
derived example(1,2,3);
cout<<example.sameName<<endl;
cout<<example.diffName<<endl;
cout<<example.base::sameName<<endl;
}
The result is 3 2 1.
I hope the example could be helpful.
A base class, even an abstract one, will be included in its entirety within any derived classes. The new allTheStuff name hides the old one, but does not suppress its inclusion; the base class version can still be accessed using Abstract::allTheStuff. Worse, the function doAllTheWork will end up accessing the base class allTheStuff because it can't possibly know there's an identically-named member variable in a subclass.
If you want this kind of behaviour, you have a few decent options:
Don't put any meaningful code or data in the base class; leave it as a pure interface. This may result in code duplication (but you may be able to factor it out into new base classes or shared helper functions).
Use a dynamically sizable container type as the Blob, so you can dynamically ask for more or less space in the constructor.
Make Blob a separate inheritance hierarchy (e.g. B_Blob and S_Blob inherit from an abstract Blob with differing amounts of space allocated), with a virtual function in Abstract that returns the Blob to use.
You seem to be somehow assuming that this code compiles using C++. It certainly doesn't. Even after patching about various of the C++/CLI specifics, it remains that a Blob does not have a data member called moreData and the only way to get at it (using C++) is to use a suitable cast.
The BulbasaurTrainingCamp objects will have two members called allTheStuff, one of type Blob and one of type B_Blob. Which one you get depends on which type you are looking at (since all members are private, you won't get any, but let's ignore that detail) and/or which qualification you use:
BulbasaurTrainignCamp btc;
B_Blob& b_blob = bts.allTheStuff;
Blob& blob1 = bts.Abstract::allTheStuff;
Abstract& abstract;
Blob& blob2 = abstract.allTheStuff;
That is, when using something which looks like a BulbasaurTrainingCamp you can access both the Blob and the B_Blob objects but you need to use qualification to access Abstracts allTheStuff member. When using an Abstract you can only access Abstracts Blob object.
Suppose I have a pure virtual method in the base interface that returns to me a list of something:
class base
{
public:
virtual std::list<something> get() = 0;
};
Suppose I have two classes that inherit the base class:
class A : public base
{
public:
std::list<something> get();
};
class B : public base
{
public:
std::list<something> get();
};
I want that only the A class can return a list<something>, but I need also to have the possibility to get the list using a base pointer, like for example:
base* base_ptr = new A();
base_ptr->get();
What I have to do?
Have I to return a pointer to this list? A reference?
Have I to return a null pointer from the method of class B? Or have I to throw an exception when I try to get the list using a B object? Or have I to change the base class method get, making it not pure and do this work in the base class?
Have I to do something else?
You have nothing else to do. The code you provide does exactly that.
When you get a pointer to the base class, since the method was declared in the base class, and is virtual, the actual implementation will be looked up in the class virtual function table and called appropriately.
So
base* base_ptr = new A();
base_ptr->get();
Will call A::get(). You should not return null from the implementation (well you can't, since null is not convertible to std::list< something > anyway). You have to provide an implementation in A/B since the base class method is declared pure virtual.
EDIT:
you cannot have only A return an std::list< something > and not B since B also inherits the base class, and the base class has a pure virtual method that must be overriden in the derived class. Inheriting from a base class is a "is-a" relationship. The only other way around I could see would be to inherit privately from the class, but that would prevent derived to base conversion.
If you really don't want B to have the get method, don't inherit from base.
Some alternatives are:
Throwing an exception in B::get():
You could throw an exception in B::get() but make sure you explain your rationale well as it is counter-intuitive. IMHO this is pretty bad design, and you risk confusing people using your base class. It is a leaky abstraction and is best avoided.
Separate interface:
You could break base into separate interface for that matter:
class IGetSomething
{
public:
virtual ~IGetSomething() {}
virtual std::list<something> Get() = 0;
};
class base
{
public:
// ...
};
class A : public base, public IGetSomething
{
public:
virtual std::list<something> Get()
{
// Implementation
return std::list<something>();
}
};
class B : public base
{
};
The multiple inheritance in that case is OK because IGetSomething is a pure interface (it does not have member variables or non-pure methods).
EDIT2:
Based on the comments it seems you want to be able to have a common interface between the two classes, yet be able to perform some operation that one implementation do, but the other doesn't provide. It is quite a convoluted scenario but we can take inspiration from COM (don't shoot me yet):
class base
{
public:
virtual ~base() {}
// ... common interface
// TODO: give me a better name
virtual IGetSomething *GetSomething() = 0;
};
class A : public Base
{
public:
virtual IGetSomething *GetSomething()
{
return NULL;
}
};
class B : public Base, public IGetSomething
{
public:
virtual IGetSomething *GetSomething()
{
// Derived-to-base conversion OK
return this;
}
};
Now what you can do is this:
base* base_ptr = new A();
IGetSomething *getSmthing = base_ptr->GetSomething();
if (getSmthing != NULL)
{
std::list<something> listOfSmthing = getSmthing->Get();
}
It is convoluted, but there are several advantages of this method:
You return public interfaces, not concrete implementation classes.
You use inheritance for what it's designed for.
It is hard to use mistakenly: base does not provide std::list get() because it is not a common operation between the concrete implementation.
You are explicit about the semantics of GetSomething(): it allows you to return an interface that can be use to retrieve a list of something.
What about just returning an empty std::list ?
That would be possible but bad design, it's like having a vending machine that can give Coke and Pepsi, except it never serves Pepsi; it's misleading and best avoided.
What about just returning a boost::optional< std::list< something > > ? (as suggested by Andrew)
I think that's a better solution, better than returning and interface that sometimes could be NULL and sometimes not, because then you explicitly know that it's optional, and there would be no mistake about it.
The downside is that it puts boost inside your interface, which I prefer to avoid (it's up to me to use boost, but clients of the interface shouldn't have to be forced to use boost).
return boost::optional in case you need an ability to not return (in B class)
class base
{
public:
virtual boost::optional<std::list<something> > get() = 0;
};
What you are doing is wrong. If it is not common to both the derived classes, you should probably not have it in the base class.
That aside, there is no way to achieve what you want. You have to implement the method in B also - which is precisely the meaning of a pure virtual function. However, you can add a special fail case - such as returning an empty list, or a list with one element containing a predetermined invalid value.
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.).