Are C++ nested classes the right approach for encapsulation? - c++

I have a global class TRK that has many members and methods. I wanted to organize these by sorting them into different named categories, e.g. Fitting, such that the namespace of the main class isn't overcrowded. In a perfect world, I would want this example to work:
class TRK
{
public:
// constructors
TRK(...);
...
TRK();
~TRK();
// nested classes
class Fitting;
// and many other methods...
private:
...
};
class TRK::Fitting
{
public:
// constructors/destructor
TRK& trk;
Fitting();
~Fitting();
// and many other methods...
private:
...
};
The key thing here that I need is to be able to:
Instance some TRK object using one of the TRK class' constructors, and I need the TRK constructors to be able to also automatically instantiate accompanying nested classes e.g. Fitting, for that instance of TRK. I then need to be able to instantiate/give values to members of these nested classes, within the TRK constructors. For example, if Fitting has some member x, I need to be able to initialize the value for x for that instance of TRK within the TRK constructor, given the arguments to the constructor. What I'm unclear on is how exactly to go about this; how and where can I instantiate these nested classes?
Access members of the nested classes from TRK instances and methods, and vice versa. I already can do the latter by passing TRK by reference to the nest classes, as shown, but I'm not sure how to do the former.
For example, I have methods of Fitting that need to use members of whatever TRK instance that that instance of Fitting was created within. Similarly, I have methods of Fitting that methods of TRK need to be able to call.
Should I even be using nested classes for this? I tried using namespaces and inheritance but I couldn't get things to work the way that I wanted. My core issue here is attempting

Constructing instances of nested classes
If you want the constructor of TRK to in turn cause the construction of a TRK::Fitting variable, the definition of TRK::Fitting must be completely known to it, a forward declaration is not enough. However, once you do that, you can intialize member variables of the nested class type just like you would always do. Here is an example:
class TRK {
class Fitting {
int x;
public:
Fitting(int x): x(x) {}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
};
Having nested classes access the parent class
A nested class is just a regular class, only its name is nested. It does not automatically know where the non-static member variables of the parent are. A simple solution is to provide the nested class with a reference to the instance of the parent class, like so:
class TRK {
class Fitting {
TRK &parent;
int x;
public:
Fitting(TRK &parent, int x): parent(parent), x(x) {}
void foo() {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(*this, y) {}
void bar() {}
};
Another option is to not store a reference to the parent in the child class, but rather to explicitly pass a reference to the parent to every member function of the child class:
class TRK {
class Fitting {
void foo(TRK &parent) {
// Use something from the parent class
parent.bar();
}
};
Fitting fitting;
public:
TRK(int y): fitting(y) {}
void bar() {}
void quux() {
fitting.bar(*this);
}
};
Calling a member function of the child class from the parent class is easy, as shown in TRK::quux().
If you want to use inheritance and have the base class be able to call functions in the derived class, then the curiously recurring template pattern can be used, like so:
template <typename Derived>
class TRK {
...
void bar() {}
void quux() {
// We need to static_cast<> ourself to get an object of type Derived
static_cast<Derived>(*this)::foo();
}
};
class Derived: TRK<Derived> {
...
void foo() {
// We can directly call any base class member functions here
bar();
}
}

Related

How to make classes inherit each other?

I have two classes ClassOne, ClassTwo each one in a separated file .h and .cpp as follow:
// ClassOne.h file
#include <ClassTwo.h>
class ClassOne : public ClassTwo {
protected:
type m_string; // Required for "ClassTwo"
}
// ClassTwo.h file
#include <ClassOne.h>
class ClassTwo : public ClassOne {
public:
method1(); // <---|
method2(); // <- Required to be available in class ClassOne.
method3(); // <---|
}
As you saw in the previous code the two classes inherit each other, but that code occurs errors error C2504: 'ClassOne': base class undefined and error C2504: 'ClassTwo': base class undefined.
The purpose of that is I want the member's functions of "ClassTow" to be available in "ClassOne" but also "ClassTwo" needs a member variable in "ClassOne".
How to make the two classes inherit from each other?
Maybe the CRTP would solve your problem. First, create the class ClassOne as a template that uses a type ClassTwo as a parameter. This type shall be the class that inherits from ClassOne:
template<typename ClassTwo>
class ClassOne
{
public:
void methodOne() {
if (you need to use methods of ClassTwo)
static_cast<ClassTwo*>(this)->methodTwo();
}
};
Then define ClassTwo as the one that inherits ClassOne specifying the template parameter with itself:
class ClassTwo : public ClassOne<ClassTwo>
{
public:
void methodTwo() {
if (you need to use methods of ClassOne)
methodOne();
}
};
Update: that is a hard way to solve the problem. There are other even simpler ones, for example to use virtual methods:
class ClassOne
{
public:
void methodOne() {
if (you need to use methods of ClassTwo)
methodTwo();
}
virtual void methodTwo() = 0;
};
class ClassTwo : public ClassOne
{
public:
void methodTwo() override {
if (you need to use methods of ClassOne)
methodOne();
}
};
Both approaches have their own pros and cons. We need to know your task in details to advise which one is better.
How to make classes inherit each other?
A class cannot possibly inherit its child. A base can only be specified in the class definition, and a class cannot be used as a base unless it has been specified. There is no way to order the two definitions in such way that both are before each other. Thus, this is not possible.
Such inheritance would also be paradoxical because a class object contains the base as a sub object within itself. As such, you would end in situation where there is One inside Two inside One inside Two inside One inside Two inside One inside Two inside One inside Two inside One inside Two inside ... can you see where this is going? It is going nowhere. The object is infinitely large because it contains infinitely deep inheritance hierarchy.
To express this in another way: Inheritance hierarchy can be seen as a directed graph. An inheritance hierarchy graph cannot contain a cycle.
The purpose of that is I want the member's functions of "ClassTow" to be available in "ClassOne" but also "ClassTwo" needs a member variable in "ClassOne".
You can have two classes, both of which having access to all of the data members and the functions like this:
struct ClassOne {
// all the member functions
// all the data members
};
struct ClassTwo : ClassOne {
// nothing here
};
Now you have two classes, both of which have access to the same data members and member functions.

"this" keyword in C++ nested classes

If I have the following nested classes:
class foo {
public:
class bar {
public:
int barMethod() const;
protected:
int barVar;
};
protected:
int fooVar;
};
and then in a .cpp, can I implement barMethod() this way?
int foo::bar::barMethod() const {
return this->fooVar + this->barVar;
}
What I mean is:
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
does this keyword in a nested class refer to all classes that are upstream in hierarchy?
No, "current" class only. Class nesting is mostly a lexical thing. Unlike in, say, Java, where an inner class can be associated with an instance of an enclosing outer class, foo::bar is pretty much like any other class that isn't nested.
If you want to associate an instance of bar with an instance of foo, you need to capture a reference or a pointer to foo in bar.

c++: inherit constructor, but change by editing methods called within constructor

Suppose I have a base class,
struct X{
std::container<class> A;
std::container<class> B;
void do_this(...){...};
void do_that(...){...};
X(classC something){
do_this(...);
do_that(...);
}
}
And I want to create a descendant, but I need to only change a couple of lines in one of the methods called in the constructor:
struct Y:X{
void do_this(...){
// make my changes
}
}
Now, when I call Y(classC input), I should get my Y struct as intended, right?
How would I do this in C++?
Now, when I call Y(classC input), I should get my Y struct as intended, right?
Wrong. Inheriting a constructor doesn't mean its body is recreated with the function calls substituted by the ones you overload. It means that to construct a Y it is sufficient to construct the X sub-object explicitly via that c'tor. So rather than hassling you with forwarding stuff, you pull the appropriate c'tor into Y to be used.
This means, same c'tor body. And everything else that is Y specific will be default initialized.
How would I do this in C++?
Simply put, you can't do it easily. Unless you mess around with dark template magic, X::X will always call X::do_this. You could also move do_this to some other class, and use that one polymorphically, but as you mentioned, this isn't an option.
If you want to add a call to Y::do_this, then write a c'tor for Y. But it won't replace the call to X::do_this, it will happen afterwards. That's the C++ object model.
As long as class Y inherits from class X and class X doesn't have a default constructor you must call its overloaded version explicitly in the overloaded class (Y):
class X{
public:
X(int _x) : x(_x){};
private:
int x;
};
class Y : public X{
public:
Y() : X(0){} // important
};
int main() {
Y y; // if you remove the default constructor of Y you'll get an error here
return 0;
}
This is tough, because the only good method would be to use virtual functions. This is however not feasible here, because virtual methods in constructors are resolved statically. This means, that if you have class A and class B : A and both of them have implemented virtual function foo, when you call foo in base class constructor it will always use base class implementation.
The one method is to use it like this:
class A {
public:
A(whatever) { }
virtual void initialize() {
// base class impl
}
};
class B : public A{
public:
// if no base default ctor, use
// B(whatever)
// : A(whatever)
B(whatever) {
}
virtual void initialize() override {
// derived class impl
}
};
template <typename T> // constraint it if you want.
T createObject() {
T object;
object.initialize(); // resolved dynamically
}

Call to base class method: accessing member of derived class

Say we have two classes:
class Parent
{
public:
vector<int> x;
protected:
void Method();
}
and
class Child : public Parent
{
public:
vector<double> x;
}
and the method Method() operates on x and makes some operation, which is compatible for both types int and double:
void Parent::Method()
{
x.push_back(1);
}
Then, if I will create an instance of Child class, initialize vector<double> x, and then call derived method Method() from the base class, C++ will try to operate on Parent's member x and not the Child's one. Is there any way how to make base class method to automatically operate on the member that belongs to created class, Child's vector<int> x?
EDIT:
As McAden correctly noted, this behavior can be easily achieved using polymorphism: three classes - 1 base and 2 derived. But does it mean that it is impossible with just 2 classes?
Since you only want to create instances of Child and you want the Child to dictate the type of the vector, this problem is more naturally solved with a template Parent. As a simple example, Parent could be parameterized by what vector<> should contain:
template <typename T>
class Parent {
public:
std::vector<T> x;
protected:
void Method () { x.push_back(1); }
};
class Child : public Parent<double> {
//...
};
If you actually have many such things you want the child to control in the Parent, then you probably should treat Child more like a traits class for the Parent. Thus, Parent would actually be parameterized by its Child, and your code would then be using CRTP. which provides "static polymorphism".
template <typename CHILD>
class Parent {
protected:
void Method () {
CHILD *child = static_cast<CHILD *>(this);
child->x.push_back(1);
}
};
class Child : public Parent<Child> {
public:
std::vector<double> x;
};
Changing data types in dealing with inheritance isn't so much possible with the exception being cases where covariance is used. If you want to make a class that handles differing data types what you're probably looking for is a template class:
http://www.learncpp.com/cpp-tutorial/143-template-classes/

Conversion of function parameter to child class c++

I have a parent class with a non virtual interface (NVI):
class Parent {
private:
virtual int do_function(void) = 0;
public:
int function(void);
virtual ~Parent() {};
}
And a child class (actually, I have a lot of child classes, but I want only this one to work this way)
class Child : public Parent {
private:
int _x;
int do_function(void) { return _x; };
public:
Child(int x): Parent(), _x(x) {}
virtual ~Child() {return do_function();};
}
And I want to call a function:
int myFunction(Parent& x) {
return x.function();
}
using the code
int x = 5;
myFunction(x);
but not the
int myFunction(const Child& x) {
return x.function();
}
which works fine.
Is it possible to do this with implicit conversion of types?
Basically you want to implicitly create a Child Object, constructed with x, and then have it passed through to myFunction( Parent& ).
You can do myFunction(Child(x));
but I think that when you try with the bare x, it tries to construct a object : Parent(x) and it fails. That isn't what you want anyway because you do want an instance of a Child object.
The way that make_pair does something similar is using a templated copy constructor on the object that is being created (pair) which creates an object of the required type(s).
I think that what you want to do can't be done in that way because you want to create the derived class and it isn't going to try to do that because the function signature is Parent&.
edit and alternative solution
I made a few attempts to create a template based solution to this by adding a templated constructor to the Parent class but it really does boil down to the fact that ultimately you need to invoke a constructor for the derived class.
I think the only sensible solution to this to allow use of the myFunction(Parent&) is to use an Indirect method that returns a reference to a Parent after constructing (temporary?) the child - that of course means you would have many such methods if you have many child classes. I realise that this is not quite as simple as passing in the int (and having it construct and pass in the ref), but it is almost what you want :)