Constructor call in composition - c++

I have the following code for composition. It generates an error,
#include <iostream>
using namespace std;
class X
{
private:
int iX;
public:
X(int i=0) : iX(i) { cout <<"Constructing X.."<<endl; }
~X() { cout <<"Destructing X.."<<endl; }
int getIX() { return iX; }
};
class Y
{
private:
X x(3);
int jY;
public:
Y(int j = 0) : jY(j) { cout <<"Constructing Y.."<<endl; }
~Y() { cout <<"Destructing Y.."<<endl; }
void callGetX() { cout <<"iX is "<<(x.getIX())<<endl; }
};
int main()
{
Y yObj(1);
yObj.callGetX();
}
Error:
In member Function void Y::callGetX()
'x' undeclared (first use this function)
Is there anything that i have missed?
Can anyone please tell me the constructor call mechanism for this scenario?

X x(3);
This is not legal in C++ (legal in Java AFAIK). In fact it makes the compiler think that x is a member function that returns an object of class X instead of considering x a member variable of class X.
Instead do this:
Y(int j = 0) : jY(j), x(3) { cout <<"Constructing Y.."<<endl; }

You put the member in your initialization list:
Y(int j = 0) : x(3), jY(j)
Your syntax:
class Y
{
private:
X x(3);
//...
};
is illegal.

Related

I am not able to use a friend function properly

I am writing a code to declare a member function of a class as a friend, but I am getting errors.
The code is
#include<iostream>
class Vect;
class Coordinate {
float x;
float y;
public:
Coordinate(float a,float b):x(a),y(b){}// constructor
Coordinate():x(0),y(0){};//constructor
display()
{
std::cout<<"\nx:"<<x<<" "<<"y:"<<y;
}
friend Vect::add(Coordinate B);
};
class Vect {
public:
add(Coordinate A)
{
std::cout<<A.x;
}
};
The exact errors are
invalid use of incomplete type 'class Vect'| and forward declaration
of 'class Vect'|
class Y; //forward declaration of class Y
class X
{
public:
int getmark(Y);
};
class Y
{
int mark;
public:
Y() {}
friend int X::getmark(Y);
};
int X::getmark(Y obj) {
cin >> obj.mark;
return obj.mark;
}
int main()
{
X a;
Y b;
a.getmark(b);
}
At first, when the object a (class X) is created, a forward declaration of class Y is necessary in order to declare the Y argument to X::getmark().
Creating object b (class Y) wont be a problem as the compiler knows class X exists (for the friend function).
Then, simply call the function getmark() through the object a.
Note: It is necessary to declare the function getmark() after the declaration of class Y, or else compiler will consider the class Y as an incomplete type.
you can use this :
class Vect;
class Coordinate
{
public:
Coordinate(float a = 0f, float b = 0f) :x(a), y(b) {}// constructor
float x;
float y;
void display()
{
std::cout << "\nx:" << x << " " << "y:" << y;
}
friend int add(Coordinate B);
};
class Vect
{
friend int add(Coordinate B);
public:
};
int add(Coordinate B)
{
std::cout << B.x << std::endl;
return B.x;
}

How do I set multiple class members in one statement in C++?

Is it possible to set multiple different class members in one statement? Just an example of how this would be done:
class Animal
{
public:
int x;
int y;
int z;
};
void main()
{
Animal anml;
anml = { x = 5, y = 10, z = 15 };
}
To "convert" Barry's comment into an answer, yes, under the conditions here:
An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions
(10.3).
Example:
class Animal
{
public:
int x;
int y;
int z;
};
int main() {
Animal anml;
anml = { 5, 10, 15 };
return 0;
}
(This Community Wiki answer was added in accordance with this meta post.)
You can always overload constructors or create methods that "set multiple different object properties in one statement":
class Animal {
public:
Animal() {
};
Animal(int a, int b, int c) {
x = a;
y = b;
z = c;
}
void setMembers(int a, int b, int c) {
x = a;
y = b;
z = c;
}
private:
int x;
int y;
int z;
};
int main() {
// set x, y, z in one statement
Animal a(1, 2, 3);
// set x, y, z in one statement
a.setMembers(4, 5, 6);
return 0;
}
Solution 1 for Animal (http://ideone.com/N3RXXx)
#include <iostream>
class Animal
{
public:
int x;
int y;
int z;
Animal & setx(int v) { x = v; return *this;}
Animal & sety(int v) { y = v; return *this;}
Animal & setz(int v) { z = v; return *this;}
};
int main() {
Animal anml;
anml.setx(5).sety(6).setz(7);
std::cout << anml.x << ", " << anml.y << ", " << anml.z << std::endl;
return 0;
}
Solution 2 for any class with x, y (https://ideone.com/xIYqZY)
#include <iostream>
class Animal
{
public:
int x;
int y;
int z;
};
template<class T, class R> T& setx(T & obj, R x) { obj.x = x; return obj;}
template<class T, class R> T& sety(T & obj, R y) { obj.y = y; return obj;}
int main() {
Animal anml;
sety(setx(anml, 5), 6);
std::cout << anml.x << ", " << anml.y << std::endl;
return 0;
}

(Re)Assignment to a 2 dimensional std::vector<bool> within a private member function

When implementing a class there is an internal object:
std::vector<std::vector<bool>> a;
The class initializes this object with the operator[] to assign false:
for(auto i = 0; i < limit; ++i) {
for(auto j = 0; j < limit; ++j) {
a[i][j] = false;
}
}
During a private member function we update this object to reflect the current state, note that object.x and object.y are type int as is new_x and new_y:
a[object.x][object.y] = false;
a[new_x][new_y] = true;
The object class being used is:
class object {
public:
object(): x(0), y(0) { }
int x;
int y;
};
Why does the compiler allow for the initialization but then says:
error: expression is not assignable
when I am reassigning the bit in the vector in the private member function?
Here is a Minimal complete verifiable example:
Object.hpp:
#ifndef OBJECT_HPP
#define OBJECT_HPP
class Object {
public:
Object(): x(0), y(0) {}
Object(int x, int y) : x(x), y(y) {}
int x;
int y;
};
#endif`
main.cpp
#include "Object.hpp"
#include <vector>
class Function {
public:
Function() : a(10, std::vector<bool>(10)) { }
void moveObjects() {
for(int i = 0; i < 10; ++i) {
editObjects(i,i);
}
}
private:
void editObjects(int new_x, int new_y) const {
a[new_x][new_y] = true;
}
std::vector<std::vector<bool>> a;
};
int main() {
Function f;
f.moveObjects();
}
Using clang to compile receives the error:
clang++-3.8 main.cpp -std=c++14
You have:
void editObjects(int new_x, int new_y) const {
a[new_x][new_y] = true;
}
That is not correct since you are now allowed to modify a in a const member function. Remove the const qualifier from the function.
void editObjects(int new_x, int new_y) {
a[new_x][new_y] = true;
}
The issue is the private member function is defined as const changing the object to be mutable resolves the issue:
mutable std::vector<std::vector<bool>> a;

'B::operator A' uses undefined class 'A'

I have found the following example in one of my C++ courses. When I try to compile it I get the following error:
'B::operator A' uses undefined class 'A'
Why does it say that class A is undefined?
#include<iostream>
using namespace std;
class A;
class B
{
int x;
public: B(int i = 107) { x = i; }
operator A();
};
B::operator A() { return x; }
class A
{
int x;
public: A(int i = 6) { x = i; }
int get_x() { return x; }
};
int main()
{
B b;
A a = b;
cout << a.get_x();
system("Pause");
}
The compiler needs to know what A is here:
B::operator A() { return x; }
But you only have a forward declaration. You need to move the declaration of class A above B
You are only allowed to use pointers to or references of incomplete types which is what have when you forward declare a type
You need to declare A above B, so that the definition of A is visible to B.
#include<iostream>
using namespace std;
class A
{
int x;
public: A(int i = 6) { x = i; }
int get_x() { return x; }
};
class B
{
int x;
public: B(int i = 107) { x = i; }
operator A();
};
B::operator A() { return x; }
int main()
{
B b;
A a = b;
cout << a.get_x();
}
This should work.

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.