create objects in object passing variables through constructor - c++

Been banging my head against this all day with many trips to google.
I have a master object that needs to create several other objects in its constructor the main object gets variables in its constructor that are passed on to the objects it creates.
class WorldManager{
public:
WorldManager(int x, int y, int z){
//do stuff
}
}
class GameManager{
public:
WorldManager world;
GameManager(int x, int y, int z){
world(x,y,z);
}
}
I get error
error: no matching function for call to `GAMEMANAGER::GraphicsManager(HWND__*&, int&, int&)'
it works untill I ask for args in the constructors of the world class

I think that you want:
class GameManager{
public:
WorldManager world;
GameManager(int x, int y, int z) : world(x, y, z) { }
};
The weird colon thing is called an initialization list, and it does construction of member objects and parent classes and a bunch of other things.
If you have more than one object that you want to construct, add them to the list:
class GameManager{
public:
WorldManager world1, world2;
GameManager(int x, int y, int z) : world1(x, y, z), world2(x, y, z) { }
};

Related

Error the default constructor of "Card" cannot be referenced -- it is a deleted function [duplicate]

So i created the class Point and want to use it as the parameter of the constructor in the class Circle , but the error : There is no default constructor for class "Point" shows up and I dont know how to fix it. The code is represented below this text:
class Point {
private:
int x, y;
public:
Point(int X, int Y) {
x = X;
y = Y;
}
};
class Circle {
private:
int radius;
Point centre;
public:
Circle(Point q, int r) {
centre = q;
radius = r;
}
};
int main() {
Point obj = Point(3, 4);
Circle obj = Circle(obj, 3);
}
The first problem is that when the constructor Circle::Cirlce(Point, int) is implicitly called by the compiler, before executing the body of that ctor, the data members centre and radius are default initialized. But since you've provided a user-defined ctor Point::Point(int, int) for class Point, the compiler will not synthesize the default ctor Point::Point(). Thus, the data member centre cannot be default initialized.
To solve this you can use constructor initializer list as shown below. The constructor initializer list shown below, copy initialize the data member centre instead of default initializing it.
class Point {
private:
int x, y;
public:
Point(int X, int Y) {
x = X;
y = Y;
}
};
class Circle {
private:
int radius;
Point centre;
public:
//--------------------------vvvvvvvvvvvvvvvvvvvv--->constructor initializer list used here
Circle(Point q, int r): radius(r), centre(q)
{
}
};
int main() {
Point obj = Point(3, 4);
Circle circleObj(obj,4);
}
Demo
Additionally, you had 2 objects with the same name obj inside main.

How to validate the initialization of a const member variable before assigning it in C++

Let's say I have this simple class with a const int member variable:
class MyClass{
public:
Myclass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) :importantNumber{x}
{
this->anotherNumber = y;
}
Since int importantNumber is const, I can only set it during the creation of the object by the constructor (with a member initialization list, as seen above).
Now, the question: how could I possibly add validation for argument x given to the constructor before actually creating importantNumber with that value? Is it possible to create a static int MyClass::validation(int a) and use it on the member initialization list of the constructor like importantNumber{validation(x)}?
Even if it's possible, is there a better way to do it?
You just add it.
MyClass::MyClass(int x, int y) : importantNumber{validate(x)}
{
this->anotherNumber = y;
}
The int validate(int original) function can now return something other than x or throw an exception or assert or ask the user for confirmation, whichever you deem appropriate.
If it is just a simple check and you don't want to write a validate function you can use a lambda:
MyClass::MyClass(int x, int y) :importantNumber{
[](int number){
assert(number > 0);
return number;
}(x)}
{
this->anotherNumber = y;
}
Although this can get a bit convoluted if you overdo it.
You can use the ternary operator condition ? true : false in the constructor if you want to validate with a simple condition:
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(x > 0 ? x : 0)
{
this->anotherNumber = y;
}
However, be warned that things can quickly become difficult to read if you overdo it with this operator.
For something more complex, you could do something like this:
int validateIntegral(int x) const
{
// Do validation on 'x'...
return x;
}
class MyClass{
public:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass::MyClass(int x, int y) : importantNumber(validateIntegral(x))
{
this->anotherNumber = y;
}
Use factory function for creating a class instead of constructor.
class MyClass
{
public:
static MyClass* create (int x, int y);
private:
MyClass(int x, int y);
private:
const int importantNumber;
int anotherNumber;
};
MyClass* MyClass::create (int x, int y)
{
return x > 0 ? new MyClass(x, y) : NULL;
}
When you need some advanced validation of parameters, factories have following advantages:
They avoid creation of object in memory if tests fail
They have more flexibility over checking parameters in initialization
list
You can return NULL if you dont need exceptions nor you want to have some ".is_valid()" member function for your class.

error using `this` in intilization list

I get the error "expected identifier" for the following code. How do I use initilization lists properly in constructors?
tanVec::tanVec(const int x, const int y, const int z): this->x(x), this->y(y), this->z(z)
{
}
You can safely remove this - it is not needed for disambiguation, because the names in the initialization list are resolved to members of your class, even if your argument list has parameters with names that would require disambiguation in the body of the constructor.
// Compiler will not confuse members x, y, and z with constructor arguments x, y, and z
tanVec::tanVec(const int x, const int y, const int z): x(x), y(y), z(z) {}
Small demo on ideone.

c++: initialising an object of a class in another class

Could not find a clear solution for this problem.
I have two classes Point and Vector. Vector is a child of Point In one of the methods of class Point I want to use an object of class Vector. I do it like this:
class Point
{
double x, y, z;
public:
// constructor from 3 values
Point(double x, double y, double z)
: x(x), y(y), z(z)
{}
// method move point
Point move(Vector vect, double dist)
{
Vector vectU = vect.unit();
return sum(vectU.multiplyScalar(dist));
}
};
class Vector: public Point
{
double x, y, z;
public:
// constructor from 3 values
Vector(double x, double y, double z)
: Point(x, y, z), x(x), y(y), z(z)
{}
// create unit vector
Vector unit()
{
double len = length();
return Vector(x / len, y / len, z / len);
}
};
When I compile this it gives me an error in line Point move(Vector vect, double dist) "Vector" has not been declared. I cannot find any useful answer for this error. How do I do this initialisation?
In C++ a class needs to be declared before it is defined. In your example with everything in one file, it has no idea what a Vector is when you define your Point::move function.
Typically, we'd have a header file per class (MyClass.h etc) and put the function definitions in a cpp file per class (MyClass.cpp)
So you need to restructure to something like:
Point.h:
#ifndef _POINT_H
#define _POINT_H
class Vector; // Forward declaration so you don't need to include Vector.h here
class Point
{
double x, y, z;
public:
// constructor from 3 values
Point(double x, double y, double z);
// method move point
Point move(Vector vect, double dist);
}
#endif // _POINT_H
Point.cpp
#include "Point.h"
#include "Vector.h"
// constructor from 3 values
Point::Point(double x, double y, double z)
: x(x), y(y), z(z)
{}
// method move point
Point Point::move(Vector vect, double dist)
{
Vector vectU = vect.unit();
return sum(vectU.multiplyScalar(dist));
}
Vector.h
#ifndef _VECTOR_H
#define _VECTOR_H
#include "Point.h"
class Vector: public Point
{
double x, y, z;
public:
// constructor from 3 values
Vector(double x, double y, double z)
: Point(x, y, z), x(x), y(y), z(z);
// create unit vector
Vector unit();
}
#endif // _VECTOR_H
Vector.cpp
#include "Vector.h"
// constructor from 3 values
Vector::Vector(double x, double y, double z)
: Point(x, y, z), x(x), y(y), z(z)
{}
// create unit vector
Vector Vector::unit()
{
double len = length();
return Vector(x / len, y / len, z / len);
}
(disclaimer, No guarantees that this will compile and work straight away, this is just to demonstrate how the code should be split up!)
Put a forward declaration:
class Vector;
at the beginning of the file.
Also, put a ; after the definition of each class.
If your class Vector
class Vector: public Point
inherits from Point, then you should not be using Vector in the base class Point (the base class shouldn't know anything about the derived class).
Also you are redefining x, y, z in your derived class Vector, which defeats the point of inheritance and can lead to very nasty behaviour when using polymorphism.
A virtual function may do the trick for you.
ie
move() Stub in the base
move() declaration in the derived.
Use pointers for dynamic binding.
eg point *x = new vector(...)
x.move()
etc etc.

Members vs method arguments access in C++

Can I have a method which takes arguments that are denoted with the same names as the members of the holding class? I tried to use this:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
x = x;
y = y;
};
};
... but it doesn't seem to work.
Is there any way of accessing the the instance the namespace of which I'm working in, similar to JavaScript's this or Python's self?
It's generally a good idea to avoid this kind of confusion by using a naming convention for member variables. For example, camelCaseWithUnderScore_ is quite common. That way you would end up with x_ = x;, which is still a bit funny to read out loud, but is fairly unambiguous on the screen.
If you absolutely need to have the variables and arguments called the same, then you can use the this pointer to be specific:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
};
By the way, note the trailing semi-colon on the class definition -- that is needed to compile successfully.
Yes, you should be able to write this using the "this" keyword (which is a pointer in C++):
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
}
In C++ the current instance is referenced by the const pointer this.
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
};
};