Templating with user defined classes as a parameter - c++

I'm having a bit of trouble with templating and composition-style coding. I have an object being created inside the constructor of another with the *this parameter. Sorry, if I'm being unclear. The code is as below:
In the outer.h file:
class outer {
public:
outer(int w, int l);
int getWidth();
int getLength();
private:
inner<outer> test(*this);
int width;
int length;
};
outer::outer(int w, int l) {
width = w;
length = l;
}
int outer::getLength() {
return length;
}
In the inner.h file
template<typename T>
class inner {
public:
inner(T &name);
private:
int top;
int bot;
};
template<typename T>
inner<T>::inner(T &name) {
top = name.getLength() /2;
bot = -name.getLength() / 2;
}
I don't know if this is allowed as I can't find anything online that addresses this. The compiler is having problems with the *this statement in outer.h.
Thanks in advance for your help.

If you're using C++03, you must perform initial assignments in the constructor.
class outer {
public:
outer(int w, int l);
int getWidth();
int getLength();
private:
// Member variables are initialized in the order they are declared here.
int width;
int length;
inner<outer> test;
};
outer::outer(int w, int l)
: width(w)
, length(l)
, test(*this)
{
}
Edit: Kerrek SB also observes that the order of your variables need to be changed. They are initialized in the order you declare them in the class and test needs to be initialized last, so the other variables are initialized.

Related

C++, Wondering why making this var static makes it passable to my function

I apologize for the odd description.
class test {
public:
const int x = 10;
int func(int arr[][x], int size);
private:
};
the above is not allowed. However, what I have below is totally fine. What does making it static change?
class test {
public:
static const int x = 10;
int func(int arr[][x], int size);
private:
};

C++ member initialization list in anonymous union of structs

I have the following class:
class LineSegW {
public:
union {
struct {
public:
int sx;
int sy;
int ex;
int ey;
};
struct {
public:
Vec2i s;
Vec2i e;
};
};
int w;
LineSegW(int _sx, int _sy, int _ex, int _ey, int _w) :
sx(_sx), sy(_sy), ex(_ex), ey(_ey), w(_w) {}
};
Vec2i consists simply of 2 integers. Now the problem is that the given constructor does not initialise the class members, except the integer w which is not in the union. When I write the constructor as
LineSegW(int _sx, int _sy, int _ex, int _ey, int _w) {
sx = _sx;
sy = _sy;
ex = _ex;
ey = _ey;
w = _w;
}
everything works as expected. Both variants produce no warnings or errors so what is wrong with the first option?

Different c++ classes where a member only differs by type

This is probably a really simple question, but I'm not sure what to search to find a solution. I have three classes as shown below:
class class_double_array {
public:
double *value;
int height;
int width;
void alloc(const int &h, const int &w);
}
class class_int_array {
public:
int *value;
int height;
int width;
void alloc(const int &h, const int &w);
}
class class_logical_array {
public:
bool *value;
int height;
int width;
void alloc(const int &h, const int &w);
}
where alloc would be:
void class_double_array::alloc(const int &h, const int &w) {
width = w;
height = h;
value = (double*)calloc(h*w,sizeof(double));
}
Is there a standard way to organize these classes in c++? This is a pretty simplified example, but I have something similar where the class methods are basically the same but depend on the type of value. In this example, i'd have to rewrite alloc for each class even though its basically doing the same thing for each class. I was looking into using templates but I couldn't quite find what I was looking for.
Like this:
template<typename T>
class T_array
{
public:
T *value;
int width;
int height;
void alloc(const int &h, const int &w)
{
width = w;
height = h;
value = (T*)calloc(h*w, sizeof(T));
}
}

Declaring readonly variables on a C++ class or struct

I'm coming to C++ from C# and const-correctness is still new to me. In C# I could declare a property like this:
class Type
{
public readonly int x;
public Type(int y)
{
x = y;
}
}
This would ensure that x was only set during initialization. I would like to do something similar in C++. The best I can come up with though is:
class Type
{
private:
int _x;
public:
Type(int y) { _x = y; }
int get_x() { return _x; }
};
Is there a better way to do this? Even better: Can I do this with a struct? The type I have in mind is really just a collection of data, with no logic, so a struct would be better if I could guarantee that its values are set only during initialization.
There is a const modifier:
class Type
{
private:
const int _x;
int j;
public:
Type(int y):_x(y) { j = 5; }
int get_x() { return _x; }
// disable changing the object through assignment
Type& operator=(const Type&) = delete;
};
Note that you need to initialize constant in the constructor initialization list. Other variables you can also initialize in the constructor body.
About your second question, yes, you can do something like this:
struct Type
{
const int x;
const int y;
Type(int vx, int vy): x(vx), y(vy){}
// disable changing the object through assignment
Type& operator=(const Type&) = delete;
};
Rather than a collection of constants, you could have a constant collection. The property of being constant seems to pertain to your use case, not the data model itself. Like so:
struct extent { int width; int height; };
const extent e { 20, 30 };
It's possible to have specifically constant data members of a class, but then you need to write a constructor to initialize it:
struct Foo
{
const int x;
int & y;
int z;
Foo(int a, int & b) : x(a + b), y(b), z(b - a) { }
};
(The example also shows another type of data member that needs to be initialized: references.)
Of course, structs and classes are the same thing.
You can initialize class const members with constructor. If you need add some other logic in constructor, but in .cpp file not in .h, you can create a private method and call it in constructor.
File.h
class Example
{
private:
const int constantMember1;
const int constantMember2;
const int constantMember3;
void Init();
public:
Example(int a, int b) :constantMember1(a), constantMember2(b), constantMember3(a + b) {
//Initialization
Init();
};
};
File.cpp
void Init()
{
//Some Logic intialization
}
This is not exactly answering the question asked, but if you wanted to have the simplicity of directly accessing member variables in a struct without getters, but wanted to ensure that nobody could modify the values, you could do something like this:
#include <iostream>
using namespace std;
class TypeFriend;
struct Type
{
const int &x;
const int y;
Type (int vx, int vy):x (_x), y (vy), _x (vx)
{
}
private:
friend class TypeFriend;
int _x;
};
struct TypeFriend
{
TypeFriend (Type & t):_t (t)
{
}
void setX (int newX)
{
_t._x = newX;
}
private:
Type & _t;
};
int main ()
{
Type t (1, 2);
TypeFriend tf (t);
cout << t.x << "," << t.y << endl;
// t.x = 6; // error: assignment of read-only location ‘t.Type::x’
// cout<<t.x << ","<<t.y<<endl;
tf.setX (5);
cout << t.x << "," << t.y << endl;
return 0;
}
The result of running this is:
1,2
5,2
Type::x cannot be modified externally, so it is read-only, but via TypeFriend it can be changed. This can be useful if you wanted to expose a simple interface of direct member access for reading, but wanted to restrict how those members could be changed.

Making a structure in class

I am making my first steps in learning OOP . And here is the first problem which I can't solve.
The max function in this class should return the maximum of two numbers . I want to keep the numbers in the private scope and the functions in the public scope . But when I want to use variables from struct data{} in the public scope the compiler says that the variables are not declared . Please tell me why I get these errors .
class myclass{
private:
struct data{
int q ;
int w;
};
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
struct data{
int q ;
int w;
};
only declares a type, not an object, so there are no q and w members anywhere inside your class instances. You need the declare an instance of the struct:
struct {
int q;
int w;
} data;
Then, you can write max as:
int max()
{
if (data.q > data.w)
return data.q;
else
return data.w;
}
(I've no idea what your get method is supposed to do, so I have no replacement for that.)
In C++ "class" and "struct" are close to being synonymous (the same thing). The ONLY difference is that a "struct" defaults to being "public" accessibility while a "class" defaults to private.
Once you understand this, it should become obvious that what you are doing is defining a sub-type within your class.
class myclass {
private: // <- not required, you already said that by saying "class".
struct data {
// <-- this is a class definition with "public:" just here.
...
};
};
C++ allows you to nest class/structure definitions so that you can, for example, create structures that marshal parameters or return values.
class Database {
class Result { ... };
};
...
class Exam {
class Result { ... };
};
These two result classes avoid namespace collision, by being Database::Result and Exam::Result instead of just "Result".
However - these are only definitions. They do not - as shown - have any effect on the outlying class, that is: they aren't being used to add a member to the class.
Your code:
class myclass{
private:
struct data{ // <-- this is a TYPE declaration, struct myclass::data
int q ; //
int w; //
}; // <-- no member name here so does not affect myclass itself.
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
Declares a type "myclass::data" but does not add a member of type "myclass::data" to the class. The line "struct data = " is illegal, you're trying to assign values to a TYPE.
It should probably be written as
class MyClass {
int m_q;
int m_w;
public:
void set(int q, int w) {
m_q = q;
m_w = w;
}
int max() const {
return (m_q > m_w) ? m_q : m_w;
// or #include <algorithm> and return std::max(m_q, m_w);
}
};
You only need to hoist q & w into a struct if you are going to reuse that structural definition outside the confines of the class, e.g. in derived or parallel classes where you may want to add more of the same type of thing, in which case, you could perhaps do the following, but if you do it this exact way you'll eventually kick yourself for breaking encapsulation:
class MyClass {
public:
struct Data {
int m_q;
int m_w;
};
private:
Data m_data;
void set(int q, int w) {
m_data.m_q = q;
m_data.m_w = w;
}
int max() const {
return (m_data.m_q > m_data.m_w) ? m_data.m_q : m_data.m_w;
}
};
A better way, if this coupling of members needs to be externally visible to some degree would be:
class MyClass {
public:
class Data {
int m_q;
int m_w;
public:
Data() : m_q(0), m_w(0) {}
Data(int q, int w) : m_q(0), m_w(0) {}
void set(int q, int w) {
m_q = w;
m_w = w;
}
int q() const { return m_q; }
int w() const { return m_w; }
int max() const { return (m_q > m_w) ? m_q : m_w;
};
private:
Data m_data;
public:
MyClass() : m_data() {} // or = default
MyClass(int q, int w) : m_data(q, w) {}
MyClass(const Data& data) : m_data(data) {}
// Read-only access
const Data& data() const { return m_data; }
// To allow write access, e.g. for set:
Data& data() { return m_data; }
};
It's kinda overkill for such a simple case, but welcome to C++: the boilerplate language.
You have defined the structure but there is no object of that type. You should declare an object and you will not get any error.
class myclass{
private:
struct data{
int q ;
int w;
}var;
public:
void get(int a, int b){
var .q= a;
var.w=b; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(var.q>var.w)
return var.q;
else
return var.w;
}
};