How can I print out the derived class name from the base class without chaining constructors all the way down. In other words is it possible to do this strictly from the base class without adding code in each derived class?
This is an example of what I got, and if there's a way I'd like to get rid of the constructor chaining.
EDIT:
Ideally I am looking for something to add into the base class without having to edit all derived classes. At the moment my real code has got ~17 classes(with need for more), so something that could do the job straight from the base class would be ideal. Even if it's compiler specific (g++ or clang).
#include <iostream>
class Base {
public:
Base(std::string id) {
std::cout<<"Creating "<<id<<std::endl;
}
};
class Child : Base {
public:
Child(std::string id) : Base(id) {}
Child() : Base(typeid(this).name()) {}
};
class GrandChild : Child {
public:
GrandChild(std::string id) : Child(id) {}
GrandChild() : Child(typeid(this).name()) {}
};
class GrandGrandChild : GrandChild {
public:
GrandGrandChild(std::string id) : GrandChild(id) {}
GrandGrandChild() : GrandChild(typeid(this).name()) {}
};
int main() {
GrandGrandChild *A = new GrandGrandChild();
GrandChild *B = new GrandChild();
Child *C = new Child();
return 0;
}
Which prints:
Creating GrandGrandChild
Creating GrandChild
Creating Child
But with compiled added prefix.
There is unfortunately no easy solution.
The problem is that constructing polymorphic objects is quite complicated, at the moment you are building the Base subpart of a Child class, you are building a Base still, not a Child (because trying to access Child members would be non-sensical, they have not been built yet!)
As such, all the ways to retrieve dynamic information (known as RTTI or RunTime Type Information) are voluntarily locked down to prevent such mistake.
For symmetrical reasons, the same occur in the destructor.
Now, only the constructor and destructor are so locked down, therefore you can perfectly have a name() method that will happily return the true name of the dynamic type of the instance in all other cases:
class Base {
public:
std::string name() const { return typeid(*this).name(); }
};
It will work... unless you invoke it from a constructor or destructor in which case it will report the static type.
Now, as far as the "bizarre" output, each implementation (compiler) is allowed to provide its own output here (and they need not even be different for different types, crazy eh!). You seem to be using gcc or clang.
There are demanglers to interpret such output, or if your program is simple enough and their interface scares you, you might simply try to parse it manually to remove the cruft. The name of the class should appear fully, it'll just be preceded with some nonsense (namespaces and numbers essentially).
you can provide an initialization function that needs to be called from each constructor.
class Base {
protected:
Base() { init(typeid(this).name()); }
void init(std::string id) {
std::cout<<"Creating "<<id<<std::endl;
}
};
You somehow need to make sure, that subsequent inits will safely supersede the changes of previous ones:
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P15GrandGrandChild
Creating P4Base
Creating P5Child
Creating P10GrandChild
Creating P4Base
Creating P5Child
I intend to use it purely for debugging purposes, which is why something to throw into the base class would be convenient.
have you considered adding a macro to your code to print the debug output?
#ifdef DEBUG
#define PRINT_CLASSNAME std::cout<<"Creating "<<id<<std::endl;
#else
#define PRINT_CLASSNAME ;
#endif
You need to add it to your constructors once, but if you want to disable it (temporarily) you just undefine it?
Since you indicate this is for debugging, you can rely on virtual inheritance to avoid passing the name through all the intermediate derived classes, and instead pass it directly to the Base. Also, Base can be modified to take a template constructor to simplify things for the derived classes.
class Base {
public:
template <typename DERIVED>
Base (DERIVED *d) {
std::cout << "Creating " << typeid(*d).name() << std::endl;
}
};
class Child : virtual public Base {
public:
Child () : Base(this) {}
};
class GrandChild : public Child, virtual public Base {
GrandChild () : Base(this) {}
}
class GrandGrandChild : public GrandChild, virtual public Base {
GrandGrandChild () : Base(this) {}
}
Related
In c++ "protected" modifier allow method calls only in derived classes. Is it possible to implement inverse logic - prohibit calling a base class method in the derived classes? The code below illustrates what I want to get.
class Base
{
int data;
protected:
// This constructor should be called only in the derived classes
Base(int d): data(d) { }
public:
// This construcor can be called wherever except a derived classes!
Base(): data(0) { }
};
class Derived : public Base
{
public:
// The developer must not forget to initialize "data"
Derived() : Base(10) {}
// I want to get a compilation error there
Derived() : Base() {}
};
Is it possible to [...] prohibit calling a base class method in the derived classes?
Yes. By using private access specifier. Private names are accessible only to the class itself.
It is not inverse logic however. It is not possible for reduce accessibility of of otherwise public name from derived classes.
// This construcor can be called wherever except a derived classes!
There is no way to do this. A public function can be called by anyone and there is no SFINAE trick you can use to stop it if it is called by a derived class since the constructor has no idea where it is called from.
This seems like a XY problem. Although I do not recommend this (I recommend rethinking the design) I found (for better or worse) a solution inspired from the CRTP pattern:
template <class D = void>
class Base
{
protected:
int data;
protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}
public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};
class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}
// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here
Derived d{};
}
Of course there are problems with this. For starters there is nothing stopping from creating a derived class as class Derived : public Base<void>.
And if you want, you can add a common base class
class Base_l0
{
};
template <class D = void>
class Base_l1 : Base_l0
{
};
class Derived : public Base_l1<Derived>
{
};
The short answer is no.
In C++, there is only public protected and private. There is no middle ground. Your functions are either accessible from everywhere (public), from nowhere except the class itself (private), or from the class and its children (protected).
I only want to force the user to perform some additional actions wlile inheritting [sic]. For example, to avoid random errors.
If calling the default constructor causes errors by calling it while inheriting from it, then then it is probable it causes errors when you are not inheriting from it. That means you probably shouldn't have this constructor as public anyway, if at all.
Today i tried to instanciate an inner class while passing my outer class to it and while i am in the namespace of the outer class:
I'm using Visual Studo 2013.
Code looks like this : (watch the ^^)
class Base
{
public:
virtual void foo(){ cout << "foo" };
};
class object
{
class Derived : public Base
{
object& o;
public:
Derived(object& o) : o(o){}
virtual void foo(){ cout << "bar" };
}derived(*this);
// ^^^^^^
};
The derived class inheriting something does not affect anything for this example here as far as i tested. (only in here for context reasons , see below)
On this ^^ point i recieve error:
no appropriate default constructor available
Intellisense warns me, that it expects type specification.
I also tried passing a pointer (of course i changed construktors then, too)but same reaction.
For protokoll i tried quite a lot of variations and research by now, but i cannot isolate a clear answer to my problem.
Is the "this" pointer not usable here ? How can i pass myself then at this point ?
For Background (only if you're interested):
I tried to write Code for Keybinding in an Application. To pass
functions to the Keys i use an "Interface" of class KeyFunction (Base
class resembles it).
I now want to give classes (object) the possibility to declare it's
own KeyFunction(Derived) and , more important, pass ressources(object)
with it, in a way that functions can work on them (since i can only
use void pointers, because they are later stored in an array for the
bindings) I already achieved this task with other code which i think
is to long to post here, though. By experimenting i stumbled across
this problem.
Your compilation error has nothing to do with your class hierarchy, but with the simple fact that this is not how you go about constructing a class instance.
Try actually declaring a class member, and a class constructor:
class Base
{
public:
virtual void foo(){ }
};
class object
{
class Derived : public Base
{
object& o;
public:
Derived(object& o) : o(o){}
virtual void foo(){ }
};
Derived derived;
object() : derived(*this)
{
}
};
OK, Not sure on the terminology for what I'm trying to do so edits are very welcome.
I've got code such as this:
class CBaseItemTracker
{
public:
CBaseItemTracker();
void IncrementCount() { ++count; }
protected:
int count;
};
class CDerivedItemTracker : CBaseItemTracker
{
public:
CDerivedItemTracker();
void Print() { printf("something:%d\ncount:%d\n", something, count); }
private:
int something;
};
class CBaseClass
{
public:
BaseClass();
private:
CItemTracker item;
};
class CDerivedClass : CBaseClass
{
public:
CDerivedClass();
CDerivedItemTracker GetDerivedItem();
private:
CDerivedItemTracker derived_item;
};
What I would like to accomplish is that CBaseClass::item and CDerivedClass::derived_item are actually the same object such that:
Code within CBaseClass can update item
Code within CDerivedClass can update derived_item (and therby also update item)
Code external to CDerivedClass can retrieve a CDerivedItemTracker object that includes the item variable.
I feel like I am trying to do something that is fundamentally wrong but I'm not seeing a good way to resolve it.
Your goal is that code within CBaseClass can update base member item and
code within CDerivedClass can update members derived_item as well as item.
Is it a member access problem ?
The first two constraints are the basics of inhertance.
The only problem in your code is that you have item member as private. This means that the derived classes won't have access to it. Just change it to be protected instead:
class CBaseClass
{
public:
BaseClass();
protected: //<===== derived classes will have direct acess to this member
CItemTracker item;
};
class CDerivedClass : CBaseClass
{
public:
CDerivedClass();
CDerivedItemTracker GetDerivedItem();
private: // you can leave it private, but if further dirved classe need access
// make it protected as well, but then you should consider public inheritance
// so that the further derived also see the item.
CDerivedItemTracker derived_item;
};
Now the derived class sees both itmes. In GetDerivedItem() you can choose which item to return. But item and derived_item will remain unrelated, as your class definitions define two distinct members.
Or is it about sharing a single (derived) item ?
The third requirement makes the things a little bit more complex. I'm not 100% sure of your intentions. But if the intention is to extend in a derived class an item of the base class, this wont be possible as such, due to C++ standard constraints on the object layout.
Fortunately there are two main alternatives: templates or dynamic member.
Template approach
The template approach should be considered if at compile time you do already make the choice of the member type.
template <class myitem>
class CBase
{
public:
CBase() {}
protected:
myitem item;
};
template <class myitem>
class CDerived : CBase<myitem>
{
public:
CDerived() {}
myitem GetDerivedItem() { return item; }
};
You can use this as follows:
CBase<CBaseItem> b;
CDerived<CDerivedItem> d;
d.GetDerivedItem().Print();
The principle is that for object d in CBase would have a CDerivedItem item, even if you would only access to the subset of its public CBaseItem members.
Dynamic approach
The dynamic approach doesn't use templates, but creates the item during the construction.
Here I present a simple implementation based on references, taking the luxury of some unused members. A more space efficient pointer based variant with dynamic allocation of the item should be prefered whenever space is critical.
class CBase
{
public:
CBase() : item(base_item) {} // when lonesome object: uses its own item
protected:
CBase(CBaseItem &itm) : item(itm) {} // when subovject of a derived class
CBaseItem &item;
private:
CBaseItem base_item; // used only for non derived CBase object.
};
class CDerived : CBase
{
public:
CDerived() : CBase(derived_item) {} // Tell the base class that there's already an item to be used.
CDerivedItem GetDerivedItem() { return derived_item; }
// we can use item as well: it'll be the CBaseItem subobject of derived_item
private:
CDerivedItem derived_item;
};
ATTENTION: for this to work you need public inhertance between item classes ( class CDerivedItem : public CBaseItem)
The difficulty here, is that base classes are constructed first. So you have to provide to the base class constructor the item reference that it has to use. If inadvertently you'd forget, the base would think it is a free object and will use a separate item. THis is why I'd suggest to use the template approach if possible.
I have several derived classes (e.g. DerivedX, where x is derived class number) that differ in fields and member functions.
Than I want to extend each derived class with some set of properties (can be organised as a field Extension ex), preserving each DerivedX class. The latter means, that we could create "clear" DerivedX objects that would not contain the property Extension ex.
The derived objects are created in some code place (e.g., in function main()), than, if they possess an extended functionality, this functionality should be used (get,set, other methods are called from main()).
The first idea was to add this new property to every derived class forming new class (ExtendedX) for each of derived classes. But I feel the code would become bulky, it seems, this approach is bad:
class Base
{
protected:
int b;
...
}
class Derived1: public Base
{
protected:
int d1;
...
};
class Derived2: public Base
{
protected:
int d2;
...
}
...X classes defined
class Extended1: public Derived1
{
protected:
Extension ex;
public:
int getExProperty1(){return ex.getProperty1();} // the realization could differ: we could also return copy of Extension object, pointer, set every field separately or the whole Extension object
}
class Extended2: public Derived2
{
protected:
Extension ex;
public:
int getExProperty1(){return ex.getProperty1();} // the realization could differ: we could also return copy of Extension object, pointer, set every field separately or the whole Extension object
}
...X classes defined
The demanded functionality is repeated in each class in that case. It's highly deprecated practice.
The other (second) idea was to declare "class Extension" that would contain the property considered ("Extension ex" in the example) and create its objects on-demand along with the objects of classes DerivedX, when we need DerivedX objects to possess this property.
The third idea was to include pointer to Extension as a field to the Base class and simply initialize it to NULL when we don't want to use the extended functionality. But then, how can we call methods of Extension class from main()?
Extended functionality could also be different in the future (derived classes are extended in accordance with the kind of problem being solved), that's why the second and the third ideas are also better, than the first.
Is there any good solution to add pack of properties and functionality to multiple derived classes?
EDIT1:
I tried to implement mixin through CRTP, as suggested by Deduplicator.
However, the code fails with:
«class Base» has no member named «getProperty1»
«class Base» has no member named «setProperty1»
The code:
#include <iostream>
using namespace std;
class Base {
int a;
public:
virtual ~Base(){}
};
class Derived1: public Base
{
public:
virtual ~Derived1(){}
};
template <class T> class Extension: public T
{
int prop1;
public:
void setProperty1(int _p){prop1=_p;}
int getProperty1(){return prop1;}
};
int main()
{
Base* der = new Derived1();
Base* e = new Extension<Derived1>();
e->setProperty1(10);
cout<< e->getProperty1();
delete der;
delete e;
return 0;
}
Changing
e->
to
static_cast<Extension<Derived1> *>(e)->
makes the code working.
How to use Extension class objects right in this case?
Use the CRTP:
// Classes implementing additions
template<class T> class Extended : public T /*, potentially additional bases */ {
// Common extension here.
}
Another option, if you can redefine the various Derived classes but can't change the definition of Base, is to shove Extension into the class hierarchy between them and Base:
class Base
{ // ...
};
class Extension: public Base
{ // ...
};
class Derived1: public Extension
{ // ...
};
class Derived2: public Extension
{ // ...
};
This way, anything that doesn't need the new APIs in Extension can continue to use Base*, and the parts that need the new API can use Extension* (or dynamic_cast<Extension>(baseptr)) instead.
This assumes Extension needs access to Base. If it doesn't, then you can just implement Extension as a mixin:
class Base
{ // ...
};
class Extension
{ // ...
};
class Derived1: public Base, Extension
{ // ...
};
class Derived2: public Base, Extension
{ // ...
};
Composition or inheritance ?
when we need Derived objects to possess this property.
This sounds as if an object and its extended property have a "has-a" and not and "is-a" relationship. This would suggest composition rather than inheritance as solution.
"on demand" , "if we don't want" ...
These suggest an optional relationship. It sounds as if you'd decide at runtime and for each object if the extension is needed or not. This reinforces the preference for composition over inheritance.
To achieve this kind of behaviour with inheritance needs polymorphism, and you'd have to use pointers/references everytime you need to work with an object.
Extended functionality could also be different in the future (derived
classes are extended in accordance with the kind of problem being
solved),
In the future, could there be further derivation for the derived ? If yes, how would this further derivation relate to the extension ? If you'd say that further derivation would be independent of the extension, then composition should definitively be the choice.
Now which one of 2 and 3 to prefer ?
Looking at all the arguments above, the third option could be very interesting for both your current needs for a common extension, but also future needs.
Here is the general idea:
class Base {
...
protected:
Extension *ex;
void setExtension(Extension *e); // to be called by ctor or the derived.
public:
bool isExtended() { return ex!=nullptr; }
int getExProperty1(){ if (isExtend()) return ex->getProperty1();} // common member functions
};
But for this to remain extensible for future evolutions, Extension should define its member functions virtual. Then later some derived class could use a derivation of Extension:
class MyDerivedExtension : public Extension { // specially for Derived1 extensions
protected:
string myspecificproperty; // specific for Derived1
public:
int getPropery1 () { /* calculate it differently than for basic Extension */ }
string getProperty2 () { /*...*/ } // specific to Derived1
};
class Derived1: public Base
{
...
protected:
void setExtension(MyDerivedExtension *e) { Base::setExtension(e); } // to be called by ctor.
public:
string getExProperty2(){ if (isExtend()) return ex->getProperty2();} // non common member
};
Please look at this code. It just reflects basic concept of what I want to do:
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
/* Some code I want to reuse */
Redefined();
}
virtual ~Base() {}
void Redefined() { val = 10; }
int val;
};
class Derived : public Base
{
public:
Derived() : Base() {}
~Derived() {}
void Redefined() { val = 25; }
};
int main()
{
Base* check = new Derived();
cout << check->val << endl;
system("pause");
return 0;
}
I want the val property of check object to be 25 instead of 10.
As you can see I have two classes. Base class constructor have some complex functionality, which I want Derived class to have in it's constructor as well. How can I change derived function Redefined so that I won't have to rewrite Derived constructor completely (in fact just copy-pasting the whole base class constructor code and replacing one single line of code - updated version of Redefined function)?
You can't really override a function that way. Normally you could use a virtual functions, but that doesn't work the way you want in the constructor.
A better way is to pass the value you want to the Base constructor:
class Base
{
public:
Base(int init_val = 10)
{
/* Some code I want to reuse */
val = init_val;
}
virtual ~Base() {}
int val;
};
class Derived : public Base
{
public:
Derived() : Base(25) {}
~Derived() {}
};
That way any derived class can pass its choice of value to the base class.
Based on comments above:
I would actually think that the correct solution is to have a "interface" type baseclass (that is, a baseclass with pure virtual functions, and the derived class actually implements the correct behaviour), and then let each class deal with constructing its own DirectX buffers. You may find that you need, say, 2-3 different derived classes that construct buffers in different ways, and then derive from those the classes that actually do the real work. I hope that makes sense.
Alternatively, you would be passing enough parameters to the base-class, such that the buffers can be constructed. But I think the first suggestion is a better choice.