Passing a variable to a constructor in c++ - c++

I'm getting started with class inheritance in c++ and I'm really stuck.
From the child class I'm trying to call the parent constructor and pass a variable as a parameter. The warning says field 'default_name' is uninitialized when used here [-Wuninitialized].
class ParentClass {
public:
ParentClass(std::string _name): name(_name) {};
std::string name;
void printname() {
std::cout << this->name << std::endl;
}
}
class DerivedClass: public ParentClass {
public:
std::string default_name = "Alex";
DerivedClass(): ParentClass(default_name) {};
}
This obviously does not work because DerivedClass() is going to be called before default_nameis even initialized. Is there a way to construct an object of the parent class from the derived class using a variable?

Parent classes are constructed first. Even though, in your program, your initialization of name appears first, that doesn't mean anything. C++ has strict construction and initialization rules. You are attempting to construct the parent class before name gets initialised.
name gets constructed after the parent class gets constructed.
So what you can do is to move name into another parent class before the existing one. That one gets constructed first, then your existing constructor will have an initialized member, to work with..

Members are always initialized in the same order: First base class sub-objects, then members in the order they are listed in the class declaration. Hence, your usage of a default initializer is more or less the same as:
class DerivedClass: public ParentClass {
public:
std::string default_name;
DerivedClass(): ParentClass(default_name),default_name("Alex") {};
}
Now it is more obvious that default_name is passed to the constructor of ParentClass before it is initialized. I think you already knew that... to fix it you have several options. As the default_name seems to be attached to the DerivedClass rather than instances of the class, you can make it static:
#include <string>
#include <iostream>
class ParentClass {
public:
ParentClass(std::string _name): name(_name) {};
std::string name;
void printname() {
std::cout << name;
}
};
class DerivedClass: public ParentClass {
public:
static const std::string default_name;
DerivedClass(): ParentClass(default_name) {};
};
const std::string DerivedClass::default_name = "Alex";
int main(){
DerivedClass{}.printname();
}

A base class has to be initialized before the current class members, hence the error. Here, you could make default_name static. That way it would be available at object construction time:
class DerivedClass: public ParentClass {
public:
static std::string default_name;
DerivedClass(): ParentClass(default_name) {};
};
std::string DerivedClass::default_name = "Alex";
Here, default_name could (should?) be const.But in fact, it would be even simpler to use a literal string here:
class DerivedClass: public ParentClass {
public:
DerivedClass(): ParentClass("Alex") {};
};

Related

Abstract class init in the initialization list

I want to understand the following c++ concept. class_a is abstract class and as per abstract class concept we cannot create any instance of it.
i have used the initlization list and abstract class as well but never used following concept.
In the code ,the initlization list of class_b, class_a is initlized. I want to understand what is meaning of initlizing it in the initilization list.
class_b::class_b(int val):nameA::class_a()
in fileA.cpp
namespace nameA
{
class class_a
{
public:
virtual ~class_a(){};
virtual void process()=0;
};
}
in fileb.h file
namespace nameB
{
class class_b : public nameA::class_a
{
public:
class_b(int val);
}
}
in fileb.cpp file
namespace nameB
{
class_b::class_b(int val)
:nameA::class_a() //Want to understand this line...
}
It would be more clear with a slightly richer example. Because if the abstract base class has neither attributes nor methods it is harder to see how it can be initialized.
class NamedProcessor {
std::string name; // a private attribute
public:
NamedProcessor(const std::string &name) : name(name) {}
virtual ~NamedProcessor() {}
// a pure virtual method to make the class abstract
virtual void process() = 0;
std::string getName() {
return name;
}
};
class Doubler : public NamedProcessor {
int value; // a private attribute
public:
Doubler(int initial = 1) : NamedProcessor("Doubler") {
reset(initial);
}
void reset(int initial) {
value = initial;
}
int getValue() {
return value;
}
// the concrete implementation
void process() {
value *= 2;
}
};
int main() {
// Compiler would croak witherror : variable type 'NamedProcessor' is an abstract class
// NamedProcessor wrong("Ill formed");
Doubler doubler;
std::cout << doubler.getName() << "\n"; // name has been initialized...
return 0;
}
Here the abstract class holds an attribute which will be available to subclasses. And this attribute has to be set at construction time because there is no public setter for it. The language has to provide a way to initialize the abstract subclass, meaning not building an object, but initializing a sub-object - here setting the name.
By deriving, every class_b object will contain a class_a sub-object.
Even if you cannot instanciate an object of type class_a, there may be a need of initializing this sub-object. Consider that an abstract class can also have members.
If you have an abstract class in terms of an interface (like in Java), this abstract class obviously needs no initialization. Nevertheless it would get a (empty) default constructor in C++, that you can call explicitly in the initialization list. (If you do not call it explicitly, it will be called implicitly.)
If class is abstract it doesn't mean that it can't have any constructor. It means that you can't use it for creating an independent object.
So here is classic inheritance mechanism:
You creating a child_class object
It calls a child_class() constructor
child_class() constructor calls base_class() constructor to guarantee that fields of base_class are built correct
Then executes child_class() constructor for the rest child_class fields
In your example you call class_a() constructor by yourself, but it will be called anyway. So in sum, it's not about abstract class, it's all about simple inheritance.
You need to have some mechanism for initializing class_a fields if they exists, that's why you can call class_a() constructor even if it's abstract class, otherwise inheritance mechanism just useless.

How does Attribute Inheritance in C++ Work?

Suppose you wanted to reproduce the following Python snippet:
class Base:
name = "base"
def announce(self):
print(self.name)
class Derived(Base):
name = "derived"
Base().announce()
Derived().announce()
... which would output:
"base"
"derived"
Initially, you may be inclined to write something like the following:
#include <iostream>
#include <string>
struct Base {
std::string name = "base";
void announce() {
std::cout << name << std::endl;
}
};
struct Derived : public Base {
std::string name = "movie";
};
int main() {
Base().announce();
Derived().announce();
return 0;
}
But here Derived.name simply shadows Base.name. Calling Derived.announce() references Base.name and prints "base".
Is there any way to implement this behaviour? Ideally without class templates if possible.
C++ doesn't work like Python (which isn't surprising, they are two very different languages after all), and member variables defined in an inherited class really defines a new variable that is unrelated to the variables of the parent class.
One possible solution is to create a second (possibly protected) Base constructor which takes the name as an argument, and then the Derived class can use it to initialize the member:
struct Base {
Base() = default; // A defaulted default constructor
std::string name = "base";
void announce() {
std::cout << name << std::endl;
}
protected:
explicit Base(std::string name)
: name{ std::move(name) } // Initialize the member
{
}
};
struct Derived : public Base {
Derived()
: Base("movie") // Initialize the base class using the special constructor
{
}
};
The default Base default constructor is needed, because if you declare another constructor the compiler won't automatically generate a default constructor for you.

Avoiding object-slicing in vector<shared_ptr<Base>>

I'm storing my game's states (collections of entities, essentially) in a vector of shared pointers. When adding states to the vector, the derived part of the states is lost and they revert to the base state class. It all compiles fine, but when I query the states' names, they all come back as DEFAULT_STATE_NAME. I've read plenty of information about object splitting, but I cannot see what is going wrong here.
State.hpp
class State {
protected:
Game &game;
public:
typedef shared_ptr<State> Pointer;
static const StateName name = DEFAULT_STATE_NAME;
explicit State(Game &game_) : game(game_) ;
virtual ~State() {}
};
Example derived state class
namespace {
class Overworld : public State {
public:
static const StateName name;
Overworld(Game &game) : State(game) {}
};
const StateName Overworld::name = OVERWORLD;
}
Game.hpp
class Game {
private:
vector<State::Pointer> states;
public:
void addState(const State::Pointer &state) {
if(!state)
throw "invalid state error";
states.push_back(state);
}
// ...
}
In order to access member methods of a derived class through a pointer (or reference) to its base class, you must use polymorphism (which you didn't). For example
struct Base {
virtual string name() const { return "Base"; }
};
struct Derived : Base {
string name() const override { return "Derived"; }
};
const Base*ptr = new Derived;
assert(ptr->name()=="Derived");
Such polymorphism only works with non-static member methods, not with data members nor with static member functions. In your case, there is no polymorphism and hence Base::name remains, well, Base::name.
In your particular case, there are two other possible solutions, though. First, you can use RTTI, though this is generally frowned upon. Another option is to keep the name as a data member in Base and pass it in at construction:
struct Base {
const string name = "Base";
Base() = default;
protected:
Base(string const&n)
: name(n) {}
};
struct Derived : Base {
Derived()
: Base("Derived") {}
};
const Base*ptr = new Derived;
assert(ptr->name=="Derived");
when there is no polymorphism (and hence no virtual table and additional indirection) involved, but at the cost of a data member name.
name in State and name in Overworld are two completely independent class-variables. They are not part of any instances state, nor can you directly query an instance for class-variables, as those cannot be virtual. In order to Access class-variables polymorphically, you need to use a virtual function.
Add such a member-function to State, and don't forget overriding it in derived classes as needed. Or, you know, you could just use the languages standard RTTI using typeid.

How to pass a class's member object to its base class's constructor?

I want to make a class that passes a member object to its parent for initialization. The below code shows what I'm trying to do.
class TQueueViewerForm1 : public TQueueViewerForm
{
private: // User declarations
DOMMsgCollectionEditorImpl m_collection;
public: // User declarations
__fastcall TQueueViewerForm1(TComponent* Owner);
};
__fastcall TQueueViewerForm1::TQueueViewerForm1(TComponent* Owner)
: TQueueViewerForm(Owner, m_collection)
{
}
This doesn't seem to work however. It looks like the constructor TQueueViewerForm() is being called before m_collection is initialized. This crashes the program since TQueueViewerForm() tries to use the uninitialized object.
So... what are my choices here? Ideally I would like to just initialize m_collection before the parent class is initialized somehow.
You have to remember the order of operations with inheritance. When you construct an instance of a class, first the base component gets constructed (i.e. your base class constructor gets run to completion); then, your class' members are initialized, and finally, your class' constructor gets run.
In this case, you're passing somewhat-random memory to your base class before it ever got initialized.
A derived class's parent constructor will always be called before the child's constructor. One option you have is to put the initialization code that you're trying to execute in a separate function in the parent class and call that function in the derived class's constructor.
class CollectionHolder {
public:
DOMMsgCollectionEditorImpl m_collection;
};
class TQueueViewerForm1 :
private CollectionHolder, // important: must come first
public TQueueViewerForm {
};
A bit too subtle for my taste. Personally, I'd try to find a design that doesn't require me to perform such gymnastics.
You can pass parameters to a base classes constructor using the initialization list of the derived classes constructor.
class Parent
{
public:
Parent(std::string name)
{
_name = name;
}
std::string getName() const
{
return _name;
}
private:
std::string _name;
};
//
// Derived inherits from Parent
//
class Derived : public Parent
{
public:
//
// Pass name to the Parent constructor
//
Derived(std::string name) :
Parent(name)
{
}
};
void main()
{
Derived object("Derived");
std::cout << object.getName() << std::endl; // Prints "Derived"
}

Testing for Type Equality without RTTI

Say B and C are derived from A. I want to be able to test whether any two instances of classes derived from A are instances of the same class, that is, whether A* foo and A* bar both point to B instances, without using RTTI. My current solution is something like this:
class A {
protected:
typedef uintptr_t Code;
virtual Code code() const = 0;
}; // class A
class B : public A {
protected:
virtual Code code() const { return Code(&identity); }
private:
static int identity;
}; // class B
class C : public A {
protected:
virtual Code code() const { return Code(&identity); }
private:
static int identity;
}; // class C
Using this method, operator== can simply test first.code() == second.code(). I'd like to remove the literal identity from the derived classes and have the code found automatically by A, so that not all of the derived classes have to repeat this idiom. Again, I would strongly prefer not to use RTTI. Is there any way to do this?
Note: I have seen recent questions [1] and [2], and this is not a duplicate. Those posters want to test the contents of their derived classes; I merely want to test the identities.
You should just use RTTI instead of reinventing the wheel.
If you insist on not using RTTI, you could use CRTP and a function-local static variable to avoid having to write the function to every derived class. Adapt from this example code I wrote for Wikipedia: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#Polymorphic_copy_construction
Another alternative is reading the vtable pointer (via this and pointer arithmetics), but that would depend on both the compiler and the platform, so it is not portable.
Your idea is on the right track; maybe you can eliminate some boilerplate with a template:
class TypeTagged {
public:
virtual Code code() const = 0;
}
template <class T>
class TypeTaggedImpl: public virtual TypeTagged {
public:
virtual Code code() const { return Code(&id); }
private:
static int id;
}
Then your client classes just need to be declared like this:
class A: public TypeTaggedImpl<A> { ... }
class B: public A, public TypeTaggedImpl<B> { ... }
The different instantiations of TypeTagged mean that the types have different id fields and hence different IDs; the virtual base type means that the code for the most derived type gets returned.
You can have the Base class to take id as a constructor parameter and implement the identity() function in base class itself. Then there is no need to repeat the code in derived classes. In the derived class constructor, you can do something like derived::derived(): base(0) Sample Code:
class A
{
public:
A(int n) : m_id(n)
{
}
virtual ~A(){}
virtual int id() const
{
return m_id;
}
private:
int m_id;
};
class B : public A
{
public:
B() : A(0)
{
}
};
you can use the both macro __FILE__ __LINE__ as your code
this will avoid the collision problem
you can map this values to an int