I'm playing with a simple little inheritance program and I accidentally tried to invoke a constructor that didn't exist and I'm trying to understand the error.
Shape.h
#pragma once
#include "stdafx.h"
#include "string"
#include "iostream"
using namespace std;
enum triangle_type
{
Isoceles,
Scalene,
Equilateral,
Right,
ThreeFourFive
};
class Shape
{
public:
//constructor/destructor
Shape();
Shape(string name);
void Test()
{
enum Color { Red, Blue, Green };
Color color;
int thisThing = Red;
}
Shape* Create(Shape* shape);
virtual string Name();
virtual double Area() = 0;
~Shape();
private:
string name;
triangle_type triangleType;
};
Triangle.h
#pragma once
#include "Shape.h"
#include "string"
class Triangle :
public Shape
{
public:
Triangle();
Triangle(string);
Triangle(int, int);
//Triangle(int); missing constructor
~Triangle();
double Area();
string Name();
private:
int height, base;
string name;
};
Triangle.cpp
#include "stdafx.h"
#include "Triangle.h"
#include "string"
using namespace std;
Triangle::Triangle()
{
}
Triangle::Triangle(string name):
Shape(name)
{
this->name = name;
}
Triangle::Triangle(int newBase, int newHeight)
{
base = newBase;
height = newHeight;
}
Triangle::Triangle(int newBase)
{
base = newBase;
//C2597-you can get an illegal reference to non-static member
//if you try to use a constructor that you don't have defined in your header file
}
double Triangle::Area()
{
return 0.5*(base * height);
}
string Triangle::Name()
{
return "Triangle!";
}
Triangle::~Triangle()
{
}
main.cppp
#include "stdafx.h"
#include "Shape.h"
#include "Triangle.h"
int _tmain(int argc, _TCHAR* argv[])
{
Shape *shape = new Triangle("My triangle");
double area = shape->Area();
Triangle *triangle = new Triangle(3); //error C2664 'Triangle::Triangle(const Triangle&)
//cannot convert argument 1 from 'int' to 'std::string'
shape->Test();
return 0;
}
I recognize that calling the constructor that doesn't exist is why there's an error when I'm calling it, but I have no idea what the error message means. It didn't ring any bells after reading it.
Pretty straightforward error:
cannot convert argument 1 from 'int' to 'std::string'
You have one constructor that takes one argument:
Triangle(string);
So that is the complete overload set that is considered. You are calling it with an int:
Triangle *triangle = new Triangle(3);
There is no other constructor to consider, so the compiler will try all implicit conversions at its disposal - all of which fail. Hence, the compile error.
The compiler will, where possible, convert between types to make a function call succeed. In your case, you have a constructor that takes one argument (a std::string) and so the compiler tries to convert the int you gave to a std::string which it expects. It can't, which is why you get that particular error.
Related
I've checked other questions with similar errors, and they didn't seem comparable to the issue that I'm running into. I'm trying to instantiate an object and assign it in a constructor initialization list.
However, on line 11, I'm getting an error saying 'Enemy' does not refer to a value.
Furthermore, also on line 11, the log is giving me: error: expected primary-expression before 'Goblin'
#include "Room.h"
#include <iostream>
#include "Enemy.h"
#include "Chest.h"
#include <string>
Room::Room(Enemy enem_obj)
:symbol{"_ "}, enemy{enem_obj}{
}
Room::Room()
: Room{Enemy Goblin{"Goblin"}}{
}
void Room::print(std::ostream& os){
os << symbol;
}
#ifndef ROOM_H
#define ROOM_H
#include "I_Mapsquare.h"
#include "Enemy.h"
#include "Chest.h"
#include <string>
class Room : public I_Mapsquare
{
private:
std::string symbol;
Enemy enemy;
Chest chest;
public:
Room(Enemy enem_obj);
Room();
virtual ~Room() = default;
virtual void print(std::ostream& os) override;
};
#endif // ROOM_H
#ifndef ENEMY_H
#define ENEMY_H
#include "I_Player.h"
class Enemy : public I_Player
{
private:
static constexpr const char* def_name = "Enemy";
static constexpr double def_hp = 20.0;
static constexpr double def_def = 3.0;
static constexpr double def_str = 2.0;
static constexpr double def_dex = 1.0;
static constexpr double def_wepdmg = 4.0;
public:
Enemy(std::string name = def_name, double hp = def_hp, double str = def_str, double defense = def_def, double dex = def_dex, double wepdmg = def_wepdmg);
Enemy(std::string name);
virtual ~Enemy() = default;
virtual void attack(I_Player& obj) override;
};
#endif // ENEMY_H
#include "Enemy.h"
#include <string>
Enemy::Enemy(std::string name, double hp, double str, double defense, double dex, double wepdmg)
: I_Player {name, hp, str, defense, dex, wepdmg}
{
}
Enemy::Enemy(std::string name)
: Enemy{name, 20.0, 3.0, 2.0, 1.0, 4.0}
{
}
void Enemy::attack(I_Player& obj){
obj.takedmg(*this);
}
I'm sure this code is beyond horrendous, as this is the first independent program I've made, and I just wanted to try to make some sort of functional program using cpp. I'm also fairly certain that I'm trying to do some sort of horribly moronic operation here and that is why this isn't compiling. Pointing me in the right direction or to some material that would help me understand what is going on here would be helpful. Thank you all for your time!
Not sure why you are trying to name this object, just
Room::Room()
: Room{Enemy{"Goblin"}}{
}
Temporaries (like Enemy{"Goblin"}) are objects without names.
The problem is that Enemy Goblin{"Goblin"} is a declaration and a declaration is not allowed inside the parenthesis () of a mem-initializer. This can be seen from base.class.init:
ctor-initializer:
: mem-initializer-list
mem-initializer-list:
mem-initializer ...opt
mem-initializer-list , mem-initializer ...opt
mem-initializer :
//-----------------------vvvvvvvvvvvvvvv------------->note this part
mem-initializer-id ( expression-list... opt )
mem-initializer-id braced-init-list
mem-initializer-id:
class-or-decltype
identifier
(emphasis mine)
As we can see above, the construct inside the parenthesis () should be an expression list but since you're providing a declaration, you get the mentioned error.
To solve this, you can skip naming the object:
Room::Room()
//---------vvvvvvvvvvvvvvv---->ok now as this is an expression
: Room{Enemy{"Goblin"}}{
}
When I have both the prototype and definition in the same header file (as shown below), and I create an object in main (source.cpp) with Cube c1{}; I get no error and the default constructor works; c1's side will be defaulted to 0.0
class Cube {
private:
double side;
static int counter;
//this is cube.h
public:
Cube(double s = 0.0) :side{ s } { //constructor
counter++;
}
};
However, when I separate the interface from the implementation like this:
class Cube {
private:
double side;
static int counter; //static data
//this is cube.h
public:
Cube(double);
};
Its implementation:
#include <iostream>
#include "Cube.h"
int Cube::counter{ 0 };
//this is cube.cpp
Cube::Cube(double s = 0.0) :side{ s } {
counter++;
}
And I go to the main function in source.cpp, Cube c1{}; now gives me the error:
no instance of constructor "Cube::Cube" matches the argument list
Note: When I gave c1 a value, like Cube c1{5}; it works in both cases.
You should put the default argument to the declaration Cube(double = 0.0);, not the definition. Otherwise the matching function cannot be found in other files.
I have two classes: "Station" which has method getName() returning string and "Profit" which has the overloaded method sellAt(string stName), sellAt(Station st). To avoid duplicate code I call sellAt(string stName) in sellAt(string stName), however in some cases (see code example below) compiler gives an error: "no instance of overloaded function "Profit::SellAt" matches the argument list. Argument types are: (std::string)". Is it a bug or I miss something?
Station.h
#pragma once
#include <string>
using namespace std;
class Station
{
private:
string sName;
public:
Station(string name);
string getName();
};
Station.cpp
#include "Station.h"
Station::Station(string name)
:sName(name)
{}
string Station::getName()
{
return sName;
}
Profit.h
#pragma once
#include "Station.h"
#include <string>
class Profit
{
public:
double SellAt(string& stName);
double SellAt(Station& st);
};
Profit.cpp
#include "Profit.h"
double Profit::SellAt(const string& stName)
{
// do stuff
}
// Works as expected
double Profit::SellAt(Station& st)
{
string stName = st.getName();
return SellAt(stName);
}
// Compile error
double Profit::SellAt(Station& st)
{
return SellAt(st.getName());
}
// Compile error
double Profit::SellAt(Station& st)
{
double result = SellAt(st.getName());
return result;
}
Yksisarvinen answered in the comment below the original question:
st.getName() is a temporary. You cannot bind non-const reference to a temporary. I suppose you shouldn't want to modify stName in Profit::SellAt(), so change the type of argument to const std::string&.
Thanks for the help!
How to avoid circular dependency on these code:
Mechanic.cpp:
#include "stdafx.h"
#include "Characters.h"
#include "Monsters.h"
using namespace characters;
using namespace monsters;
using namespace std;
void character::character_atack(character const cha, monster &monst)
{
if (cha.dexterity + k(20) >= monst.defense)
monst.health = monst.health - cha.strength;
}
int k(int const max)
{
return (rand() % max);
}
void monster::monster_atack(character &cha, monster const monst)
{
if (monst.atack + k(20) >= cha.dexterity)
cha.health = cha.health - monst.damage;
}
Monsters.h:
#include <iostream>
#include <string>
namespace monsters
{
using namespace std;
class monster{
protected:
string name;
public:
int atack;
int damage;
int health;
int defense;
monster(int atk, int dmg, int hp, int def) : atack(atk), damage(dmg),
health(hp), defense(def) {}
~monster();
void monster_atack(character &cha, monster const monst);
};
class greenskins:monster{
greenskins(int atk, int dmg, int hp, int def) : monster(atk, dmg, hp, def) {}
};
}
Characters.h:
#include <iostream>
#include <string>
#include <vector>
namespace characters
{
using namespace std;
class character{
protected:
int level;
int experience;
string name;
public:
int health;
int strength;
int intelligence;
int dexterity;
struct position{
int x;
int y;
}pos;
character(int str, int in, int dex) : strength(str), intelligence(in),
dexterity(dex), level(1), experience(0) {
cout << "What's your name?" << endl;
cin >> name; }
~character();
void info_character();
void character_atack(character const cha, monster &monst);
};
}
The compilator gives me errors like this:
Error 1 error C2061: syntax error : identifier 'monster'
or
Error 9 error C2511: 'void monsters::monster::monster_atack(characters::character &,const monsters::monster)' : overloaded member function not found in 'monsters::monster'
The issue is that character has a function that takes a monster& and monster has a function that takes a character&, but you don't declare the other class in either case. Thankfully, since you just pass the classes as arguments in both places (as opposed to having them be members or something), it is sufficient to forward-declare both classes in both places:
// in character.h
namespace monsters {
class monster; // just fwd-declare
}
namespace characters {
class character {
// as before
};
}
And similar in the other file.
[update] Also, you're just referencing monster inside of class character in the header file, you need to qualify it as monsters::monster.
The first error comes from the following line in Characters.h
void character_atack(character const cha, monster &monst);
You include Characters.h into your .cpp file before you include the Monsters.h and thus the type monster is not yet known. To fix this, change your Characters.h to look like this:
... //includes
namespace monsters {
class monster;
}
namespace characters {
class character {
... //class definition
}
}
The second error is a not matching signature. You are declaring following method:
void monster_atack(character &cha, monster const monst)
but defining
void monster::monster_atack(character &cha, const monster monst)
At least that is what the compiler said.
I would suggest to change the signature to:
void monster_atack(character &cha, const monster& monst)
to prevent needless copy operations. (depending on optimization of course)
I get the following error message when I try to run my program:
main.cpp|44|error: type/value mismatch at argument 1 in template
parameter list for 'template<class _Tp, class _Alloc> class
std::vector' main.cpp|44|error: expected a type, got '(render)3u'
main.cpp|44|error: template argument 2 is invalid main.cpp|44|error:
invalid type in declaration before ';' token
=== Build finished: 4 errors, 0 warnings (0 minutes, 0 seconds) ===
And here is my code for main leading up to the error causing line:
#include<stdlib.h>
#include<windows.h>
#include<GL/glut.h>
#include<GL/freeglut.h>
#include<iostream>
#include <vector>
#include "include/Block.h"
#include <string>
#include <sstream>
#include "include/TextBlock.h"
#include "include/Enemy.h"
string text;
stringstream ss;
enum render {Normal,SelectRangeText,SelectSText,Enemy,EnemyTypeSelection};
enum render state;
enum type { Foreground, Background, Midground };
enum type selected;
enum types { Blocks, Enemies, Text };
enum types special;
string names[4] = { "grass" , "smallGrassBlock" , "dirt" , "sand" };
void createEnemy(int,int);
void addEnemyWaypoint(int,int);
void addToList(vector<Block> &list,int x,int y);
void placeText(int x,int y);
void initTextures();
GLint GetTexture(string file);
void IdleFunction();
void removeBlock(int x,int y);
int xOffset,yOffset,multiuse = 0;
using namespace std;
string to_string(int number);
void placeBlock(int x,int y);
void drawBitmapText(char *string, float x, float y, float z);
void reshape(int w, int h);
void render(void);
void keyboard(unsigned char c,int x,int y);
void mouse(int button,int state, int x, int y);
void arrows(int key, int x, int y );
std::vector <Block> backBlockList;
std::vector <TextBlock> textBlockList;
std::vector <Block> midBlockList;
std::vector <Block> foreBlockList;
std::vector <Enemy> enemyList;//error occurs here
GLuint textures[1];
unsigned int screenXSize=800;
unsigned int screenYSize=800;
unsigned int selectedBlockType = 1;
int main(int argc, char ** argv)
{
The header for enemy:
#ifndef ENEMY_H
#define ENEMY_H
#include<GL/freeglut.h>
#include <vector>
class Enemy
{
public:
Enemy(int Type );
virtual ~Enemy();
void render(int,int,GLuint);
void addWaypoint(int,int);
protected:
private:
int type;
std::vector <int> X, Y;
int xsize,ysize;
};
#endif // ENEMY_H
And the constructor for enemy:
Enemy::Enemy(int Type)
{
xsize=30;
ysize=30;
type=Type;
}
However it will run corrrectly if I substitute the type of my vector to an int.
When the following line is commented out: std::vector enemyList; it compiles, however if it's there it doesn't
when declaring an Enemy like this
Enemy e(5);
it runs correctly
Updates:
If i change the enemy header, and cpp to something like the following:
CPP:
#include "../include/Enemy.h"
Enemy::Enemy( )
{
}
Enemy::~Enemy()
{
//dtor
}
Header
#ifndef ENEMY_H
#define ENEMY_H
class Enemy
{
public:
Enemy( );
~Enemy();
protected:
private:
};
#endif // ENEMY_H
It still crashes with the same error, this means it must be something in main
FIX:
For some reason when I declare it in the line above my enums it works, however if below it doesn't, I have no idea why. If someone could explain this please go ahead.
For some functions, std::vector<T> requires that T be default-constructible. Your Enemy class cannot be default-constructed, therefore the compiler issues an error. Either define a default constructor for Enemy, do not call vector functions that require default constructibility, or change the vector to be of a different type.
Given the virtual use in Enemy, and that std::vector<Enemy> could never accept a derived class, plus your use of disgusting global variables, C arrays and otherwise terrible code, I am going to posit that you have no idea what is going on.
A std::vector<Enemy> can only ever hold an Enemy. It cannot hold a derived class of Enemy or anything else. It can only hold Enemy. If you wish to have a vector of things that might be various derived classes, you must use a pointer of some degree of ownership. This means you must solve the problem of who owns the objects being pointed to, and further that you must understand the concept of ownership and what smart pointers are available. This is essential knowledge for C++ and you won't get far without it.
To have a vector of some value type, the type must have an available no-argument constructor, which yours doesn't (ie. that's what the error message is telling you). However, since I doubt you want to copy around Enemys, you should store them by pointer,ie.
vector<Enemy*> enemies;
for (int i = 0; i < NUM_ENEMIES; ++i)
enemies.push_back(new Enemy(type));
EDIT I just noticed you have the following declaration
class Enemy...
but you also declare an enum value
enum render {... ,Enemy, ....
I just compiled the following code and got a suspiciously similar error:
#inlcude <vector>
class A {};
enum type {A, B, C};
std::vector<A> As;
int main(int argc, char** argv)
{
return 0;
}
So there's your problem. When it comes time to resolve the template, the compiler sees an enum value (which can be a template parameter, just like any other integral type), and assumes that's the one you meant. However, since no vector template matches (they all have a class as the first template parameter), it doesn't compile. Hence, your error.