Inheritance and array of types - c++

I have a probably very simple question in C++.
Let's say I have class defined as:
class PS
{
private:
int value;
int m;
public:
PS();
PS(int value, int m);
PS(int m);
};
Now I want to define an array with elements of this type. For example,
PS t[3];
However, I want all of the elements in this array to have m=2. How would I do that? I am assuming I have to use inheritance some how, right?
So for example I don't want to do something like this:
>PS t[3];
>t[0].PS(2);
>t[1].PS(2);
>t[2].PS(2);
I want to do it one show for all elements of t.

Using your constructor, you can simply use brace initialization :
PS t[] = { PS(2) , PS(2), PS(2) };
Or as suggested by #0x499602D2, since PS has a non explicit constructor, simply :
PS t[] = { 2, 2, 2 };
I would also suggest you to use std::array<> instead of C-style arrays.

It is not really safe not to initialize a value but you can use the C++11 feature that allows you to initialize variable directly in your class definition :
class PS {
private:
int value;
int m = 2;
public:
PS() {};
};
If you are using an older version of C++ you can consider overloading the default constructor
class PS {
private:
int value;
int m;
public:
PS(int _m = 2) : m(_m) {};
};

The STL Vector class is preferred to c-arrays. Using one, you could do:
std::vector<PS> t(3, PS(2));

Related

Expand variadic template to array of static members

I've defined a base class template:
template<class actual_class>
class base
{
public:
static const int value;
}
and the definition of value depends on the actual_class tparam.
Next, I have a bunch of derived classes from base, let's call them a and b. Let's also say that a::value = 5 and b::value = 10.
Now, in a method template where I need to access the static values from a parameter pack. I'd like to have them in a vector.
template<class... derived_from_bases>
void foo(irrelevant_class<derived_from_bases...> irrelevant)
{
// std::vector<int> values = { ... }
...
}
For the function called with < a, b > tparams I'd like the values vector to look like this:
std::vector<int> values = {5 /* a::value */, 10 /* b::value */};
Also having an std::array instead of an std::vector would be a nice touch.
Thank you for your help in advance.
For a vector, you just need
std::vector<int> values = { derived_from_bases::value... };
If you have C++17, you can get a std::array the same way like
std::array values = { derived_from_bases::value... };
and CTAD will deduce the type and size of the array for you. If you do not have C++17, then you can use
std::array<int, sizeof...(derived_from_bases)> values = { derived_from_bases::value... };

Initializing struct via member initialization list

So I'm learning C++ from Stephen Prata book and I want to do one exercise... So the problem is this:
I want to use a std::valarray inside a struct, inside a class like this:
class Wine
{
private:
struct Pair
{
std::valarray<int> valYear;
std::valarray<int> valBottlesNum;
};
int m_yearNum;
Pair m_numericData;
public:
Wine();
Wine(int, const int[], const int[]);
};
And initialize this via member initialization list:
Wine::Wine(int yearNum, const int year[], const int bottlesNum[])
: m_yearNum(yearNum),
m_numericData.valYear(yearNum, year),
m_numericData.valBottlesNum(yearNum, bottlesNum)
{}
But it just doesn't want to work. Somehow compiler does not like this "." to access members of a m_numericData struct in a initializer list.
I could just abandon Pair struct and do valYear and valBottlesNum as a simple class member variables and initilize them like this...
Wine::Wine(, int yearNum, const int year[], const int bottlesNum[])
: m_yearNum(yearNum), m_valYear(yearNum, year), m_valBottlesNum(yearNum, bottlesNum)
{}
but I really want to know how to solve this kinda stuff.
Thanks in adavnce!
You can move the individual initialisations into the body of the constructor:
Wine::Wine(int yearNum, const int year[], const int bottlesNum[])
: m_yearNum(yearNum)
{
m_numericData.valYear = std::valarray<int>(yearNum, year);
m_numericData.valBottlesNum = std::valarray<int>(yearNum, bottlesNum);
}
Alternatively, give Pair its own constructor.
The valarray constructor you're attempting to use takes a T const* to the data and an std::size_t argument indicating the number of array elements that the first argument points to. If you can use C++11, then change yearNum to std::size_t and you can use list-initialization, which in turn will aggregate initialize the Pair.
Wine::Wine(std::size_t yearNum, const int year[], const int bottlesNum[])
: m_yearNum(yearNum)
, m_numericData{{year, yearNum}, {bottlesNum, yearNum}}
{}
Live demo

Convert C array literal to work in C++ constructor?

I have some C code that I'm trying to convert/wrap into a C++ class. I ran into some C literal arrays(correct me if I'm calling them wrong) and I'm not sure how to initialize them in the C++ constructor since I don't think you can do literals, which I think are compile time specific, to something that is runtime specific.
Should I just explicitly define the array to be of a certain size and just do a strcpy, or some such, of the literal to the array in the constructor?
char sysUpTime[] = {1,3,6,1,2,1,1,3,0};
As an alternative to initializer lists or string manipulation, you could use something like the following (if you really wanted to):
struct Wrapper
{
template <size_t N>
Wrapper(const char(&arr)[N]) : vec(arr, arr+N) { }
vector<char> vec;
};
I've left everything public due to chronic laziness on my part :). You can then initialise like this:
char foo[] = { 1, 2, 3, 4, 5 };
Wrapper bar(foo);
copy(bar.vec.begin(), bar.vec.end(), ostream_iterator<int>(cout, ", "));
Could just use std::string to store OID then initialize it in member initializer list for example:
#include <string>
class Wrapper
{
public:
Wrapper() : sysUpTime("1.3.6.1.2.1.1.3.0") { }
private:
std::string sysUpTime;
};
Or use C++11 std::array
class Wrapper
{
public:
Wrapper() : sysUpTime{{1,3,6,1,2,1,1,3,0}} { }
public:
std::array<char, 10> sysUpTime;
};
The main problem when passing different size c-style arrays to a constructor is that you must pass the size along with it. Here's an example of putting the array into a member vector:
#include <vector>
#include <iostream>
struct Test
{
std::vector<char> sysUpTime;
Test(const char sysUpTime[], size_t size) :
sysUpTime(sysUpTime, sysUpTime + size)
{ }
};
int main()
{
const char sysUpTime[] = {1,2,3,4,5};
Test test(sysUpTime, sizeof(sysUpTime) / sizeof(char));
}
Unfortunately I know of no way to do this without using a dynamic array (vector), aside from using templates which means that you'll get a separate class instantiated for each and every change in the size of your array.

How can I create an array of class objects whose constructor require few arguments?

I've read about solution const A a[3] = { {0,0}, {1,1}, {2,2} }, but in my program const can't be used:
class Paper: public PaperQueue{
...
protected:
typedef int (Utils::*funcPtr) (int, int); //I use external function there
funcPtr p;
Utils* fptr;
public:
int pricefunc(){
addprice = (fptr->*p) (t,price);
}
Paper(int n, unsigned int pr):PaperQueue(n){
...
p=&Utils::commonpricefunc;
}
void Put(int a){
...
}
...
}
class Bank{
...
void Buy(Paper &p){
(/*this function modifies many parameters in 'p'*/)
...
}
...
}
int main(){
Bank B;
int pn=5;
/* ? */ const Paper p[pn] = {{5,15},{5,15},{5,15},{5,15},{5,15}}; /* ? */
int paperloop=0;
...
p[paperloop].Put(p[paperloop].addprice);
B.Buy(p[paperloop]);
...
That gives me a LOT of errors(with pricefunc(),Put(),Buy(),...), or just "variable-sized object ā€˜pā€™ may not be initialized". Is there any way to make this array work? (Everything works fine if not to pass any parameters to constructor!)
You can't use initializer lists for classes (non-PODs) because that would bypass the call to the constructor. You'll have to change it to a POD or use std::vector in the following ways:
If the class is copyable, as it appears to be, you can create a std::vector and fill it with the values you want:
const vector<Paper> papers(5, Paper(5, 15));
If you want to initialize it with different values, you can use an initializer list, but this is only supported in C++11:
const vector<Paper> papers = {Paper(1, 1), Paper(2, 2)};
Without C++11, you'll have to add the elements one by one, but then you can't make the vector const:
vector<Paper> papers;
papers.push_back(Paper(1, 1));
papers.push_back(Paper(2, 2));
Please check the code below, it can be compiled:
class Paper {
public:
int x, y;
};
int main() {
Paper p[5] = {{5,15}, {5,15}, {5,15}, {5,15}, {5,15}};
}
Please refer this post for more details, I think it explains very well

Problems Initializing Vector

I'm new to c++ so I'm kind of consfused
I wanted to do something like that:
`
int max = 30;
class MyClass{
vector<int> data(max);
};
but it wasn't working, because it was not recognizing that "max" was that int I had just initialized.
so i changed to that:
class MyClass{
MyClass();
int max;
vector<int> data(max);
}
MyClass::MyClass(){
max = 40;}
Don't work unless I initialize the vector in the constructor, but I don't know the correct sintax.
How can I make this work? All I want is to initialize "max" and then use it as the initial size of the vector.
You prof/teacher should have told you about initializer lists. The syntax looks something like this:
class MyClass {
std::vector<int> data;
public:
MyClass(int max) : data(max) { }
};