I am doing OOP in C++ for the first time. I have noticed it's very different from other languages in which I have done OOP in the past.
It's been going great so far, but I have encountered an issue where I need a constructor to receive an object that I have created as parameter and for some reasons it refuses to compile and throws errors.
I made a deep research about the problem online, but I do not see cases that look enough like mine and answers vary a lot. I would like the proper way to solve this problem, so I can follow these conventions throughout my whole project.
Here is the header file where the error has been thrown (Player.h):
#pragma once
// Header files
#include "Square.h"
class Player
{
private:
// Private variables
Square _position;
public:
// Public constructors declarations
Player(Square position);
// Public functions declaration
void setPosition(Square position);
Square getPosition();
};
Here is the CPP file where the error has been thrown (Player.cpp):
// Header files
#include "Player.h"
// Public constructors
Player::Player(Square position) // <---------- ERROR LOCATION
{
_position = position;
}
// Public functions
void Player::setPosition(Square position)
{
_position = position;
}
Square Player::getPosition()
{
return _position;
}
Just in case, here is the header file of the parameter object (Square.h):
#pragma once
class Square
{
private:
// Private variables
int _x;
int _y;
public:
// Public constructors declarations
Square(int x, int y);
// Public functions declaration
void setX(int x);
int getX();
void setY(int y);
int getY();
};
Here is also the CPP file of the parameter object (Square.cpp):
// Header files
#include "Square.h"
// Public constructors
Square::Square(int x, int y)
{
_x = x;
_y = y;
}
// Public functions
void Square::setX(int x)
{
_x = x;
}
int Square::getX()
{
return _x;
}
void Square::setY(int y)
{
_y = y;
}
int Square::getY()
{
return _y;
}
Here are the errors thrown by the compiler:
At line 4 of the file 'Player.cpp':
Error E0291: no default constructor exists for class 'Square'
Error C2512: 'Square' : no appropriate default constructor avaible
The issue is that Player::_position needs to be constructed before your opening brace in any Player constructor. You can either
Create a default constructor (one that can be called without arguments) for Square. This may or may not be appropriate for your program.
Use an initializer list. This avoids design issues if Square can't have a default constructor for some reason.
The initializer list solution looks like this:
Player::Player(Square position)
: _position{position} { }
Looks like the default constructor is implicitly deleted. You may try adding a trivial one as follows (as public in Square.h.
Square(): _x(0), _y(0){}
~Square(){}
Given that you implemented a constructor for Square, the compiler doesn't implement the default constructor. Your only way to construct Square is using the constructor you defined.
Once you declared the Player's member variable Square _position, it shall be initialized somehow on Player's constructor. However, the compiler can't use the constructor you provided.
You can declare the default constructor yourself, by:
Square() = default;
The error code is shown in the first line of the constructor, because the compiler is trying to initialize every member of Player before executing the body of the constructor, but it can't find a suitable way to construct Square.
Another solution is to initialize the member variable directly using the constructor you provided. This way, the compiler will use your constructor when initializing Player's member variables:
Square _position = Square(0,0)
Related
Still fresh on C++ so I apologize if this is a stupid question,
I'm trying to declare a class in a header file that calls a initialization function while passing the arguments from the constructor.
I figure I'm doing a lot wrong, so any and all code corrections / practices are welcome.
Main.cpp:
#include <iostream>
#include "Main.h"
void Class::_init(int i)
{
this->initValue = i;
}
//not sure if this is the correct syntax
Class::Class(int i)
{
//throws an error with "truple" ~ Not Sure What That Means
this->_init(i);
}
Main.h:
#pragma once
class Class
{
//note this is simplifying the class, but keeps the concept
private:
int initValue;
void _init(int i);
public:
Class(int i);
};
So I mistook the error I was getting for an issue concerning the constructor arguments not being able to be incorporated, turns out I just needed to assign default values to said arguments which I hadn't thought of doing.
Error Was: "no appropriate default constructor available" : C2512
//.h
class Class {
public:
//sets default value for argument
Class(Object obj = Object(*Constructor Argument*));
}
//.cpp
Class::Class(Object obj) {
//code
}
I've looked at a few other questions about this, but I don't see why a default constructor should even be called in my case. I could just provide a default constructor, but I want to understand why it is doing this and what it affects.
error C2512: 'CubeGeometry' : no appropriate default constructor available
I have a class called ProxyPiece with a member variable of CubeGeometry.The constructor is supposed to take in a CubeGeometry and assign it to the member variable. Here is the header:
#pragma once
#include "CubeGeometry.h"
using namespace std;
class ProxyPiece
{
public:
ProxyPiece(CubeGeometry& c);
virtual ~ProxyPiece(void);
private:
CubeGeometry cube;
};
and the source:
#include "StdAfx.h"
#include "ProxyPiece.h"
ProxyPiece::ProxyPiece(CubeGeometry& c)
{
cube=c;
}
ProxyPiece::~ProxyPiece(void)
{
}
the header for cube geometry looks like this. It doesn't make sense to me to use a default constructor. Do I need it anyways?:
#pragma once
#include "Vector.h"
#include "Segment.h"
#include <vector>
using namespace std;
class CubeGeometry
{
public:
CubeGeometry(Vector3 c, float l);
virtual ~CubeGeometry(void);
Segment* getSegments(){
return segments;
}
Vector3* getCorners(){
return corners;
}
float getLength(){
return length;
}
void draw();
Vector3 convertModelToTextureCoord (Vector3 modCoord) const;
void setupCornersAndSegments();
private:
//8 corners
Vector3 corners[8];
//and some segments
Segment segments[12];
Vector3 center;
float length;
float halfLength;
};
Your default constructor is implicitly called here:
ProxyPiece::ProxyPiece(CubeGeometry& c)
{
cube=c;
}
You want
ProxyPiece::ProxyPiece(CubeGeometry& c)
:cube(c)
{
}
Otherwise your ctor is equivalent to
ProxyPiece::ProxyPiece(CubeGeometry& c)
:cube() //default ctor called here!
{
cube.operator=(c); //a function call on an already initialized object
}
The thing after the colon is called a member initialization list.
Incidentally, I would take the argument as const CubeGeometry& c instead of CubeGeomety& c if I were you.
Member initialization occurs when the constructor begins. If you do not provide an initializer in the constructor's member initialization list, the member will be default constructed. If you want to copy constructor to be used to initialize the member cube, use the member initialization list:
ProxyPiece::ProxyPiece(CubeGeometry& c)
: cube(c)
{ }
Everything following the colon is the initialization list. This simply says that cube should be initialized with c.
As you had it, the cube member was first default initialized and then c was copy assigned to it.
I'm trying to learn to c++ after programming in other OO languages for many years.
I'm trying to create a wrapper class for another class, but having a hard time figuring out how to set this up properly.
For instance, with the following...
main.cpp
#include "foo.cpp"
#include <iostream>
int main() {
Foo foo(42);
std::cout << foo.get_barx() << std::endl;
return 0;
}
foo.cpp
#include "bar.cpp"
class Foo {
public:
// I'm trying to declare the member variable `m_bar` here. I
// don't want to be instantiating an instance of Bar yet,
// but I think that might be exactly what's happening.
Bar m_bar;
Foo(int y) {
// Here's where I really want to instantiate an instance of Bar
// and assign it to m_bar.
Bar m_bar(y*2);
}
int get_barx() {
return m_bar.getx();
}
};
bar.cpp
class Bar {
public:
int m_x;
// I seem to need this default constructor for the declaration
// of `m_bar` above, but I don't think that line should be
// calling any constructors.
Bar() { m_x = 21; };
Bar(int x) {
m_x = x;
}
int getx() {
return m_x;
}
};
When I compile and run this, I get back 21, but I expect 84. I'm pretty sure I'm doing something fundamentally wrong, and I'm pretty sure it's got something to do with how I'm declaring the m_bar member variable in Foo, but I can't figure out what the right way is to accomplish this.
main.cpp
#include "foo.cpp"
#include <iostream>
int main()
{
Foo foo(42);
std::cout << foo.get_barx() << std::endl;
return 0;
}
Here you should be including a header (e.g., rename "foo.cpp" to "foo.h"). In general, the header provides the declaration and the source (e.g., .cpp file) provides the definition/implementation.
Bar.cpp (again this should be a header)
class Bar
{
public:
int m_x;
// A default constructor is not required, however defining any constructor
// prevents auto generation of the default constructor
Bar(int x) : // This starts the initializer list section
m_x(x)
{
// This is assignment not initialization
// m_x = x;
}
// See the trailing 'const', research const correctness
int getx() const
{
return m_x;
}
};
foo.cpp (again this should be a header)
#include "bar.cpp"
class Foo
{
public:
// Just declaring a `Bar` data member
Bar m_bar;
Foo(int y) :
m_bar(y) // Initialize `Bar` data member using the available constructor
{
// First, this declares a new `Bar` instance which is different than
// the class member, regardless of the fact they are named the same
// Bar m_bar(y*2);
// Furthermore, even if you did the following it is assignment not initialization
// m_bar = Bar(y*2);
// Since initialization already occurred before this point an error
// will result if the `Bar` data member isn't instantiated via the
// only available constructor, since there isn't a default constructor as
// explained above
}
// Same comment about const correctness
int get_barx() const
{
return m_bar.getx();
}
};
You need to use initialization lists to construct class members at construction time. The body of the constructor gets called after all members have been constructed. If you don't explicitly call a non-default constructor then the compiler will insert a call to the default constructor for you. For example, your Foo class could look like:
class Foo {
public:
Foo(int y) : m_bar(y*2) {}
...
private:
Bar m_bar;
}
I've looked at a few other questions about this, but I don't see why a default constructor should even be called in my case. I could just provide a default constructor, but I want to understand why it is doing this and what it affects.
error C2512: 'CubeGeometry' : no appropriate default constructor available
I have a class called ProxyPiece with a member variable of CubeGeometry.The constructor is supposed to take in a CubeGeometry and assign it to the member variable. Here is the header:
#pragma once
#include "CubeGeometry.h"
using namespace std;
class ProxyPiece
{
public:
ProxyPiece(CubeGeometry& c);
virtual ~ProxyPiece(void);
private:
CubeGeometry cube;
};
and the source:
#include "StdAfx.h"
#include "ProxyPiece.h"
ProxyPiece::ProxyPiece(CubeGeometry& c)
{
cube=c;
}
ProxyPiece::~ProxyPiece(void)
{
}
the header for cube geometry looks like this. It doesn't make sense to me to use a default constructor. Do I need it anyways?:
#pragma once
#include "Vector.h"
#include "Segment.h"
#include <vector>
using namespace std;
class CubeGeometry
{
public:
CubeGeometry(Vector3 c, float l);
virtual ~CubeGeometry(void);
Segment* getSegments(){
return segments;
}
Vector3* getCorners(){
return corners;
}
float getLength(){
return length;
}
void draw();
Vector3 convertModelToTextureCoord (Vector3 modCoord) const;
void setupCornersAndSegments();
private:
//8 corners
Vector3 corners[8];
//and some segments
Segment segments[12];
Vector3 center;
float length;
float halfLength;
};
Your default constructor is implicitly called here:
ProxyPiece::ProxyPiece(CubeGeometry& c)
{
cube=c;
}
You want
ProxyPiece::ProxyPiece(CubeGeometry& c)
:cube(c)
{
}
Otherwise your ctor is equivalent to
ProxyPiece::ProxyPiece(CubeGeometry& c)
:cube() //default ctor called here!
{
cube.operator=(c); //a function call on an already initialized object
}
The thing after the colon is called a member initialization list.
Incidentally, I would take the argument as const CubeGeometry& c instead of CubeGeomety& c if I were you.
Member initialization occurs when the constructor begins. If you do not provide an initializer in the constructor's member initialization list, the member will be default constructed. If you want to copy constructor to be used to initialize the member cube, use the member initialization list:
ProxyPiece::ProxyPiece(CubeGeometry& c)
: cube(c)
{ }
Everything following the colon is the initialization list. This simply says that cube should be initialized with c.
As you had it, the cube member was first default initialized and then c was copy assigned to it.
in a book i am reading to learn basic c++, there is this example:
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y);
int get_x();
int get_y();
};
void Point::set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int Point::get_x() {
return x;
}
int Point::get_y() {
return y;
}
My question is, is it not possible in c++ to include the definition of the member functions inside the class itself? The above seems quite messy. The book says to define a class member function you should use 'return_type class_name::function(){arguments}. But in C# you can just do it within the same class and it is less code. I haven't been able to find much about properties in c++. Thanks for help.
Although it is possible, it's not really recommended. Actually, the way it's done in your book isn't how it should be done either (and hopefully, later on in the book that will change!). The way you'll see it done 99% of the time (yes, I pulled that number out of my ass) is a class definition in a header file (.h extension) and the definitions in a source file (.cpp extension). The header file will be imported so to speak, into the source file via #include.
You can define the members within the class as such.
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int get_x() { return x; }
int get_y() { return y; }
};
However, this isn't a popular style of coding in C++. Most C++ conventions suggest that you separate the implementations (definitions) from the interface (the declarations) in different files (definitions would go into Point.cpp, and declarations would go into Point.h), unless the definitions are very short (like accessors).
You can define functions in the class definition in C++. This will cause them to be inline implicitly but that shouldn't matter because compilers have flexibility in terms of actually inlining. Usually this isn't done because it will increase compile time due to larger amounts of code being processed and the canonical C++ way it to put the method definitions in a separate source file.
class Point
{
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{ x = new_x; y = new_y; }
int get_x()
{ return x; }
int get_y()
{ return y; }
};
of course you can write
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{
x = new_x;
y = new_y;
}
int get_x()
{
return x;
}
int get_y()
{
return y;
}
};
But whole point is to separate declaration and implementation.
Yes we can Define a function inside a class.it has following advantage.
1)the function which you define inside a class is treated as an "inline" function .
(inline keyword before any function suggest compiler to place body of the definition of the function to where ever that function is been called from at compile time)
2)due to which inline function execute Faster.then normal function.
(remember its totally up to the compiler to make that function inline or not.you cannot force compiler to make it inline)
Most answers point out that it is possible but not recommended, I do not agree with the latter. For simple one-liner accessors it just makes sense to provide them inside the class definition in most cases:
class point {
int x,y;
public:
// ...
int posX() const { return x; }
int posY() const { return y; }
};
As of the setters, it will depend on whether you want to verify any invariant or not. In the former case, you might want to move it to a single translation unit, but even there if the checks are small I would just inline them inside the class definition.
The recommendations for separating declaration and definition of the member methods include things like:
smaller compile time: false, the compiler can parse the accessor trivially, it will not add much more to the parsing
smaller code size: false, if the function is not inlined, then the compiler must generate code for the function call, including calculation of the this pointer and actually perform the call. The inlined accessor will just require the reading of the member which will take less code.
higher compile time coupling: any change in the implementation of the function will require recompilation of all translation units that include the header... True, if you change the function, which for such a simple accessor will not happen.