How to make brace initialization and default values work together? - c++

The following code works
class A
{
public:
int i;
float f;
};
int main()
{
A a{ 1, 0.1 };
return 0;
}
However, if I add default values for A's members, it doesn't work
class A
{
public:
int i = 0;
float f = 3.14;
};
How to make both work together?

You have to define a default and a custom constructor like the example below:
class A
{
public:
A() {}
A(int const _i, float const _f) : i(_i), f(_f) {}
int i = 0;
float f = 3.14;
};
LIVE DEMO
However as already mentioned by #Kerek SB, #T.C. in the comments this will be fixed in C++14 and your code will work as is.

Related

Getting one private member from one class to another

So, I have an algorithm that takes a few sensors, scales them to a temperature and puts the temps in a global data store. However, sensor class A does more calculations that Class B needs. I can't put the new calcs in the data store, and i don't want to include class A inside class B just to get one piece of data with a getter.
Class A
{
private:
float x[4];
float y[4];
public:
//Scaling functions, etc...
}
Class B
{
private:
float c[4];
public:
//Scaling functions etc...
}
What would be the best way to get x[4] passed to class B to put in c[4]? The real classes have much more going on, this is about as simple as I think I can make. x[4] has data that needs to be used in class B.
class A
{
private:
float x[4];
float y[4];
public:
float* getXs()
{
return x;
}
}
class B
{
private:
float c[4];
public:
//Scaling functions etc...
void setXs(float *x)
{
for (int i=0;i<4;i++)
c[i] = x[i];
}
}
Well, you could use friends, if you're not willing to write accessors:
http://en.wikipedia.org/wiki/Friend_class
Some would argue this breaks encapsulation, and that a getter would be the preferred approach.
Use a getter of x[4] on an instance of A when calling the constructor of B.
#include <string.h>
class A
{
private:
float x[4];
float y[4];
public:
float const *xArray() const
{
return x;
}
};
class B
{
private:
float c[4];
public:
void setCArray(float const arr[4])
{
memcpy(c, arr, 4 * sizeof(int));
}
};
int main()
{
A a;
B b;
b.setCArray(a.xArray());
}
There are number of ways. The best depends on Your criteria.
If time is not crucial for you I would be simple and use copy constructor:
Class A
{
private:
float x[4];
float y[4];
public:
const float& X(int i) { return x[i]; }
}
Class B
{
private:
float c[4];
public:
B( const A& a ) {
for( k = 0; k < 4; k++ )
c[k] = a.X(k);
}
}
If time is crucial you can consider to use pointers copy. But be Very accurate with it:
Class A
{
private:
friend B;
float x[4];
float y[4];
public:
...
}
Class B
{
private:
const float* const c;
public:
B( const A& a ):c(a.x){}
// use c like c[4], but don't change it.
}

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

single constructor to create objects with different data types

How to use a single constructor only to create the following objects using C++:
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
class A should be having a single constructor to accomodate the creation of objects x, y and z. No change is allowed in the 3 lines specified above.
You cannot(rather should not!) have a single constructor to create all these objects.
You can have constructors which can take different parameters precisely for this reason.
The important question to be asked is:
What exactly are you trying to achieve? What is the need for this?
Perhaps you are trying to solve a problem in wrong way. If you can provide some detail We could help you better.
Yuck!!!!
Anyway, if I was forced to (for example if this, hypothetically speaking, were a homework problem) I would use some sort of variant:
class Variant {
public:
Variant();
Variant( int );
Variant( double );
Variant( const char * );
~Variant();
private:
union data { ... };
enum type { ... };
};
And then use that in my horrid single constructor, along with default arguments to allow empty construction.
A::A( Variant p1 = Variant(), Variant p2 = Variant(), Variant p3 = Variant() );
With c++11:
#include <iostream>
struct A
{
template<typename... Args> A(Args&&... x)
{
std::cout << "construct A\n";
}
};
int main()
{
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
return 0;
}
In C++03 you can use initialization funntion:
class A
{
public:
A(int x, const char* y, double z)
{
Init(x, y, z);
}
A(const char* y, int x)
{
Init(x, y);
}
A()
{
Init();
}
private:
void Init(int x = 0, const char* y = 0, double z = 0)
{
}
};
In C++11 you can use constructor delegation:
class A
{
public:
A(int x, const char* y, double z)
{
}
A(const char* y, int x)
: A(x, y, 0)
{
}
A()
: A(0, 0, 0)
{
}
};
Why not just:?
class A {
public:
A(...) { }
};
// test:
int main() {
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
}

Non-const used in a constexpr : what does the standard say?

What does the C++11 iso standard say about such an expression :
class MyClass
{
public:
constexpr int test()
{
return _x;
}
protected:
int _x;
};
_x is a non-const used in a constexpr : will it produce an error, or will the constexpr be simply ignored (as when we pass a non-const parameter) ?
It's perfectly fine, though somewhat useless:
constexpr int n = MyClass().test();
Since MyClass is an aggregate, value-initializing it like that will value-initialize all members, so this is just zero. But with some polish this can be made truly useful:
class MyClass
{
public:
constexpr MyClass() : _x(5) { }
constexpr int test() { return _x; }
// ...
};
constexpr int n = MyClass().test(); // 5
If the expression does not resolve to a constant expression, then it cannot be used as such. But it can still be used:
#include <array>
constexpr int add(int a, int b)
{
return a+b;
}
int main()
{
std::array<int, add(5,6)> a1; // OK
int i=1,
int j=10;
int k = add(i,j); // OK
std::array<int, add(i,j)> a2; // Error!
}