Making parent class members unmodifiable for each derived class - c++

I'm wondering how can I make unmodifiable a parent class member which will be different for each derived class.
My code now assigns its value correctly (depending on the Child class that calls the parent class' constructor), but m_type can be easily modified (in myfunction, for example) and that's what I'd like to avoid.
#include <iostream>
enum Piece_type{ king=1, queen=3, rook=3, bishop=4, knight=5, pawn=6};
class Piece
{
protected:
Piece_type m_type; // static Piece_type m_type; <- doesn't work
Piece(Piece_type ex): m_type(ex) {}
};
class Pawn: public Piece
{
public:
Pawn():Piece(pawn) {} // To initialise m_type as pawn for all my Pawn objects
void myfunction()
{
std::cout<<"My piece type is "<< m_type<<std::endl;;
m_type= knight; // This is the assignation I want to avoid happening
std::cout<<"My new piece type i "<<m_type<<std::endl;
}
};
My question is related to this one, but inheritance doesn't seem to make possible to declare a static variable and define its value through a member initializer.
I've found how to call the parent/base class constructor from the Child class in this question.
Thanks in advance,
Eduardo
Edit
I've slightly modified it so that not to confuse anyone, because const does work where I said it didn't.

Well, you didn't fall into the usual mistake of trying to use const member variables without a member initializer list, so const is all you need really:
class Piece
{
protected:
Piece_type const m_type;
Piece(Piece_type ex) : m_type(ex) { }
};
class Pawn : public Piece
{
public:
Pawn() : Piece(pawn) { }
void myfunction()
{
// m_type = knight; // Compile-time error
}
};

They only ways to prevent a derived type from modifying it's parent's members is to make those members private or const. Since you can't make the member const the only other way would be to declare the member private and adding a protected accessor method such as :
Piece_type get_type() const
{
return m_type;
}
This way, derived classes can call get_type() to know m_type's value but can't access it directly, preventing them from writing to it.

Related

friend function pointer parameter in constructor

i'm trying to create a costructor in the form
class A {
public:
A(void (*initializer)(A&))
{
initializer(*this);
}
};
where initializer take a reference to the instance he's passed and can make custom operation on variable it is initializing. Is there a way to make such a function friend so it can access to private variables too?
Here is a simple way:
class Impl
{
public:
int x;
int y;
};
class A
{
public:
A(void (*initializer)(Impl&))
{
initializer(_impl);
}
private:
Impl _impl;
};
This hides _impl from everyone except initializer. And since nobody other than initializer can access _impl at all, the members of of class Impl can be public, making it easy for initializer to mutate them.
Other than listing all the functions you want to pass pointers to as friends separately, no. An alternative may be to separate the data into a base class with public members you inherit privately from:
struct AData
{
int m_privateInt;
...
};
class A : private AData {
public:
A(void (*initializer)(AData&))
{
initializer(*this);
}
};
You may need to also pass a reference to A, if you want to access its member functions in initializer.

How do you access member functions of a class object from within a different class object that has been created in it?

class Class1 //Would be object mClass1
{
public:
void Function1()
{
a++;
}
private:
int a = 0;
Class2 mClass2;
}
(Editing in a space here to clarify Class2 is not defined after Class1; they are in separate files.)
class Class2 //Would be object mClass2
{
public:
Function2()
{
Function1(); // Would be from mClass1
}
}
So Class1 creates an instance of a Class2 object, and that Class2 object has a member function that wants to access the "parent" object's member function, without using inheritance.
I don't know what I specifically need to search for to learn about this. Does it have to do with dereferencing a new pointer? Constructor type/initialization? Does it have a terminology? "Nested classes" bring up classes defined inside another class, which is not what this is.
Without inheritance there is no way to get the 'parent class'. So instead you should just pass the function as a parameter, maybe in the constructor of class 2 if you use it multiple times. See for example: https://www.cprogramming.com/tutorial/function-pointers.html
You cannot do this. Class2 is not known yet when you define Class1, so the Class1::mClass2 data member cannot possibly be created. But this problem can be solved by defining Class2 before Class1, and implementing Class2::Function2() outside the class and only after Class1.
As for calling Function1() inside Function2(), Class2 needs to know the object on which to call Function1(). You could use a reference member for that that you initialize in the constructor:
// Forward-declaration of Class1 so that Class2 will be able to define
// references or pointers to Class1.
class Class1;
class Class2
{
public:
// Constructor that requires a reference to our parent object.
explicit Class2(Class1& parent)
: parent_(parent)
{ }
// Just declare the function. We need to implement it later, outside
// this class definition because Class1 is not fully known yet and as
// a result we can't have calls to Function1() because the compiler
// doesn't know that function yet.
void Function2();
private:
// This is just a reference, so it works even if Class1 is not fully
// known yet.
Class1& parent_;
};
class Class1
{
public:
void Function1() { /* ... */ }
private:
int a = 0;
Class2 mClass2{*this}; // Pass ourself as the parent object.
};
// Class1 is fully known now, so we can do calls to Function1().
inline void Class2::Function2()
{
parent_.Function1();
}
This will work, but it has an important implication: it disables the assignment operator of Class2. This is probably what you want in this case, because two copies of Class2 should probably not have the same Class1 parent object.
However, I don't see why you need to do this. It complicates matters for no good reason. Why not simply pass the Class1 object that Function2() should use as a function argument instead? So:
class Class1;
class Class2
{
public:
void Function2(Class1& c1_obj);
};
class Class1
{
public:
void Function1() { /* ... */ }
private:
int a = 0;
Class2 mClass2;
};
inline void Class2::Function2(Class1& c1_obj)
{
c1_obj.Function1();
}
So whenever Class1 needs to call Class2::Function2(), just pass *this to it. It's simpler and doesn't have the drawbacks of holding a reference or pointer to another object.
With canonic classes - no way to do this, because Class2 is incomplete within Class1 and if you declare Class2 inside of Class1 (as a nested class), it wouldn't have access to Class1, because Class1 incomplete!
Looks like an unsolvable paradox? It is unsolvable in OOP land, but can be dodged just like Nikos had shown. But the problem of undefined types in some cases can be resolved in C++ or similar concept-oriented languages by using CRTP - Curiously recurring template.
If it is possible or not in your use-case and how complex it would be depending on what purpose you pursue. Here is an example of a paradoxical CRTP behavior - a member of base class is able to call a member of derived class:
#include <iostream>
template < class T>
class Base {
public:
template <class U>
struct Accessor : public U {
static void evoke_foo( T& obj)
{
return (obj.*(static_cast< void(T::*)() >(&Accessor::foo))) ();
}
};
void evoke( )
{
Accessor<T>::evoke_foo( *static_cast<T*>(this) );
}
};
class Derived : public Base<Derived> {
protected:
void foo() { std::cout << "Foo is called" << std::endl; }
};
int main()
{
Derived a;
a.evoke(); // evoke belongs to base.
}
Now if we'd want to determine return type of foo() automatically here, this would become an insanely complex piece of code. Some problems like that are solved in implementations of standard namesake of evoke method.

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.

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"
}