How to set parent members when creating inherited struct in C++ - c++

I have a struct type A, which I could instantiate with A(p_a1, p_a2) and a struct type B, which inherits from A, that I can instantiate with B(p_b1, p_b2, p_b3).
Is there a standard way to create a B instance while also setting p_a1 and p_a2? Would I just set them after creating the B instance with b.p_a1 = v_a1; b.p_a2 = v_a2?
(Sorry for any incorrect use of terminology. I don't have much experience with C++.)
Thanks

You are looking for a C++ feature named constructor initialization lists. This example should clarify it to you:
#include <iostream>
class Foo
{
public:
Foo( int x )
{
std::cout << "Foo's constructor "
<< "called with "
<< x
<< std::endl;
}
};
class Bar : public Foo
{
public:
Bar(int x, int y, int z) : Foo( x ) // construct the Foo part of Bar
{
std::cout << "Bar's constructor" << std::endl;
}
};
int main()
{
Bar stool(10,11,12);
}

What you intend to do is achievable using initialization lists and can be done as follows:
struct A
{
A(int _a):a(_a){}
};
struct B : public A
{
B(int _a, int _b):A(a), b(_b){}
} ;
In the sample code which you have provided, what you are doing in these lines b.p_a1 = v_a1; b.p_a2 = v_a2 is called assignment. While the former will invoke just the right constructor, latter would invoke the default constructor.

Try the following
struct A {
int _a1;
int _a2;
A(int a1, int a2); //assume it is defined
};
struct B : public A {
int _b1;
B(int p1, int p2, int p3);
};
B(int p1, int p2, int p3)
: A(p1,p1), // <<== This is where parent member variables will be initialized.
_b1(p3) //or some other way to populate _b1
{ }
google "C++ constructor initialization list"

Related

C++ using 'this' keyword in member initialization list

I was writing an Integer struct
struct Integer
{
int value;
Integer(int value_) : value(_value){ }
};
This works fine but instead I wanted to use value name for the parameter too and this causes a name clash. That's why I tried to use this keyword like below
struct Integer
{
int value;
Integer(int value) : this->value(value){ }
};
But I got an error and I don't seem to understand the problem here. I would be very happy to learn. Thanks for your answers.
This works fine but instead I wanted to use value name for the parameter too and this causes a name clash.
No it doesn't.
Integer(int value) : value(value){ }
This is just fine (if a little confusing to some).
It is simply not permitted in the language grammar to write this-> there, probably because it would make no sense to specify any other object: the this-> is implicitly done for you.
The standard way is to write
struct Integer
{
int value;
Integer(int value) : value(value){ }
};
In the initializer list : value(value), the first value refers to the member (because that's what a member initializer initializes), while the second value refers to the constructor argument (because that's an expression, and the name in an expression is looked up by the ordinary rules).
As other answers already mentioned, it is not defined in the C++grammer / syntax.
See it here.
And there is no need to specify this. To disambiguate class vs. member you don't use this, you use the scope resoultion operator.
See this (strange) example:
#include <iostream>
class A{
public:
A(int a){
std::cout << "A("<< a << ")\n";
}
A(){
std::cout << "A()\n";
}
};
class B : public A
{
public:
int A;
B(int a) : A::A(42), A(a)
{}
};
int main()
{
B b = 12;
std::cout << b.A;
return 0;
}
And of course this already exists:
#include <iostream>
class B;
class A{
public:
A(int a){
std::cout << "A("<< a << ")\n";
}
A(){
std::cout << "A()\n";
}
A(B& b);
};
class B : public A
{
public:
int A;
B(int a) : A::A(*this), A(a)
{}
};
inline A::A(B& b){
std::cout << "A(B&)\n";
}
int main()
{
B b = 12;
std::cout << b.A;
return 0;
}

Accessing a parameter via a C++ function object class

#include <iostream>
struct A {
explicit A(int a) : _a(a) {};
int _a;
};
struct ClassFunction {
ClassFunction(std::shared_ptr<A> myA) : _myA(myA) {}
double operator() (int &x,
int &g) {
return 1.0
+ static_cast<double>(_myA->_a); // offending line
}
static double wrap(int x, int g, void *data) {
return (*reinterpret_cast<ClassFunction*>(data)) (x,g);
}
std::shared_ptr<A> _myA;
};
int main() {
int x = 1;
int g;
auto myA = std::shared_ptr<A>(new A(int(20)));
ClassFunction myClassFunction(myA);
std::cout << ClassFunction::wrap(x,g,NULL) << std::endl;
return 0;
}
I'm trying to create a function object class ClassFunction that takes a std::shared_ptr<A> as a parameter, which I then call via the static member function ClassFunction::wrap.
If I access a data member of A as myA->_a the program fails to run (it does compile without any complaint, however).
How do I make this work?
Try the following:
std::cout << ClassFunction::wrap(x, g, &myClassFunction) << std::endl;
reinterpret_cast< ClassFunction*>(data) is applicable when the data points to instance of ClassFunction class.

Using an interface class as member type in another class

I'm trying to design a piece of code that entails the use of an algorithm. The algorithm should be easily replaceable by someone else in the future. So in my LargeClass there has to be a way to invoke a specific algorithm.
I provided some example code below. My idea was to make an interface class IAlgorithm so that you have to provide an implementation yourself. I thought you could initialize it to which ever derived class you wanted in the constructor of the LargeClass. However the below code doesn't compile in VS2015 because IAlgorithm: cannot instantiate abstract class
My question: How should I design this in order to get the result I want?
Thanks in advance!
Algorithm.h
class IAlgorithm
{
protected:
virtual int Algorithm(int, int) = 0;
};
class algo1 : public IAlgorithm
{
public:
virtual int Algorithm(int, int);
};
class algo2 : public IAlgorithm
{
public:
virtual int Algorithm(int, int);
};
Algorithm.cpp
#include "Algorithm.h"
int algo1::Algorithm(const int a, const int b)
{
// Do something
}
int algo2::Algorithm(const int a, const int b)
{
// Do something
}
Source.cpp
#include "Algorithm.h"
class LargeClass
{
private:
IAlgorithm algo;
};
int main()
{
}
My first thoughts on this would be, why use such a primitive interface?
OK, we have a requirement that some process needs an algorithm sent into it. This algorithm must be polymorphic, it must take two ints and return an int.
All well and good. There is already a construct for this in the standard library. It's call a std::function. This is a wrapper around any function object with a compatible interface.
example:
#include <functional>
#include <iostream>
class LargeClass
{
public:
using algorithm_type = std::function<int(int,int)>;
LargeClass(algorithm_type algo)
: _algo(std::move(algo))
{}
int apply(int x, int y) {
return _algo(x,y);
}
private:
algorithm_type _algo;
};
int test(LargeClass&& lc) {
return lc.apply(5,5);
}
int divide(int x, int y) { return x / y; }
int main()
{
// use a lambda
std::cout << test(LargeClass{ [](auto x,auto y){ return x + y; } });
// use a function object
std::cout << test(LargeClass{ std::plus<>() } );
// use a free function
std::cout << test(LargeClass{ divide } );
// use a function object
struct foo_type {
int operator()(int x, int y) const {
return x * 2 + y;
}
} foo;
std::cout << test(LargeClass{ foo_type() } );
std::cout << test(LargeClass{ foo } );
}

Convert a program that uses includes to one using templates

I have created an example to show the language features I am using, the real case is not as simple. The include file is included twice, once for each class. Even though the text is the same, the underlying types are different. In the real case some variables have more initialization than others depending on the class.
Working program
ex1.cpp
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
#include "ex1.h"
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
#include "ex1.h"
};
int main()
{
one c1(1,2);
two c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
ex1.h
void f()
{
std::cout << ( a + b ) << std::endl;
}
I was hoping to change this to a program that uses templates as follows, but I get a compile error.
ex2.cpp
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
void f();
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
void f();
};
template<typename X>
void X::f()
{
std::cout << ( a + b ) << std::endl;
}
int main()
{
one c1(1,2);
two c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
The error message is error: invalid use of template type parameter 'X'
I believe the correct way to do what you want is to use a template to handle the different types present in the class:
#include <iostream>
template<typename X>
class foo {
public:
foo(X a1, X b1) : a(a1), b(b1) {}
X a,b;
void f();
};
template<typename X>
void foo<X>::f()
{
std::cout << ( a + b ) << std::endl;
}
int main()
{
foo<int> c1(1,2);
foo<double> c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}
Generally speaking you don't want to #include code directly into your class to remove code duplication, c++ gives you some better options.
You can see this run here: http://coliru.stacked-crooked.com/a/34d146d7feac8abd
CRTP to the rescue:
template<class D>
struct f_support {
void f() {
// does not block all errors, but catches some:
static_assert( std::is_base_of< f_support, D >::value, "CRTP failure" );
auto* dis = static_cast<D*>(this);
std::cout << ( dis->a + dis->b ) << std::endl;
}
};
then:
class one: public f_support<one> {
...
class two: public f_support<two> {
...
You could move the implementation of f_support<D> into a .cpp file, but that is a hassle.
I would like to thank #Yakk and #shuttle87 for their answers. I took the simplicity of shuttle87's answer and the flexibility of Yakk's answer to come up with this one. Without your help, I would still be using include files. The problem with my solution below is that it requires all classes to have the same number of arguments in their constructor.
#include <iostream>
class one {
public:
one(int a1,int b1) : a(a1), b(b1) {}
int a,b;
void g() { std::cout << "one\t"; }
};
class two {
public:
two(double a1,double b1) : a(a1), b(b1) {}
double a,b;
void g() { std::cout << "two\t"; }
};
template<class X, typename Y>
class three : public X {
public:
three(Y a, Y b) : X(a,b) {}
void f()
{
X::g();
std::cout << ( X::a + X::b ) << std::endl;
}
};
int main()
{
three<one,int> c1(1,2);
three<two,double> c2(3.4,5.7);
c1.f();
c2.f();
return 0;
}

C++ static const members overriding

Consider the following.
struct A {
static const int X = 1;
static void printX() {std::cout << "X " << X << std::endl; };
};
struct B: public A {
static const int X = 2;
};
int main(argc argv){
B b;
b.printX();
}
How to force the b.printX() to print value 2?
Both - constant and method - MUST be static. And therefore, virtual methods are not suitable.
For anyone who thinks they know my task better than me and wants to see me rethinking it, I'll explain the goal of my efforts :)
Just imagine class which has behaviour based on set of static constants. The simplest way to implement child class with different set of constants and therefore with different behaviour is derivation of class from previous one with specific set of constant values. It is possible to solve that task using virtual functions. Of cause possible, no question. But this solution will be not very pure in sense of accordance to a theory of modeled entities. Usage of virtual methods in this case will be more a trick than correct implementation.
For example, IR channels have different timing of pulse durations and package structure. It is convenient to define set of child classes (different IR channel implementations) with a specific set of constant values. That values are static because they are common for every object of class and const because they are needed at compile time only. And because internal implementations of base and child classes are slightly different the best relationship between of them are super class - child class.
Is it rationale for my original question now?
You are going to need a template, and to change the inheritance to use the template, as you will see. The trick is to make it work whether the derived class has an X to overshadow the base-class X or not.
template<class C>
struct A {
static const int X = 1;
template<typename T>
static int getX(decltype(T::X)*)
{ return T::X; }
template<typename T>
static void getX(...)
{ return X; }
static void printX()
{ std::cout << "X " << getX<C>(0) << std::endl; }
};
struct B: public A<B> {
static const int X = 2;
};
struct B2: public A<B2> {
// No X
};
int main(){
B b;
b.printX(); // Prints X 2
B2 b2;
b2.printX(); // Prints X 1
}
Just make the value of X a template parameter:
#include <iostream>
template<int XValue=1>
struct A {
static const int X = XValue;
static void printX() {std::cout << "X " << X << std::endl; };
};
template<int XValue=2>
struct B: public A<XValue> {
};
struct C: public B<3> {
};
int main(int, char**){
B<> b;
b.printX();
}
By definition, anything you do with static members will be "overshadowing", not "overriding". You could reimplement "printX()" in "B", but you would not really be overriding the behavior; because this would use overshadowing, the behavior would depend entirely on the compile-time, not runtime, type.
Instead of using static and template, I would just use regular constant attributes and constructors.
For example:
#include <iostream>
struct A {
A(const char* fn, const int X) : filename(fn), X(X) {};
void print() { std::cout << "X = " << X << ", FN = " << filename << std::endl; };
protected:
const char* filename;
const int X;
};
struct B : public A {
B() : A("data.dat", 5) {};
};
int main(int, char **) {
B b;
b.print();
}
Functionally, it does exactly what you want. Output:
X = 5, FN = data.dat
— It's now the compiler's job to optimize those constants. And if you are not intending to use thousands of objects B, it's probably not worth worrying about making those constants static.
Short answer: you can't.
Slightly longer, more complex answer: Well, maybe you can. With templates!
#include <iostream>
template <typename T> struct A
{
static const int X = 1;
static void printX()
{
std::cout << "X=" << T::X << std::endl;
}
};
struct B : public A<B>
{
static const int X = 2;
};
int main(int, char **)
{
B b;
b.printX();
return 0;
}
OK, I'll play along... you want to nest this more than one level deep. Fine.
#include <iostream>
template <int XX> struct T
{
static const int X = XX;
static void printX()
{
std::cout << "X=" << X << std::endl;
}
};
struct AA
{
static const int X = 1;
/* all other members go here */
};
struct A : public AA, public T<AA::X>
{
/* empty - put stuff in AA instead */
};
struct BB : public AA
{
static const int X = 2;
};
struct B : public BB, public T<BB::X>
{
};
struct CC : public BB
{
static const int X = 3;
};
struct C : public CC, public T<CC::X>
{
};
struct DD : public CC
{
static const int X = 4;
};
struct D : public DD, public T<DD::X>
{
};
int main(int, char **)
{
A a;
B b;
C c;
D d;
a.printX();
b.printX();
c.printX();
d.printX();
return 0;
}
You could even skip the static const int X = ...; in every class, and just do public T<1>, public T<2> etc as necessary.