Are the two forms of default class constructor equivalent? - c++

When I try the two forms of constructor in classes of derivation hierarchy, the result turns out to be different. Could anybody tell me why? Below are the test code.
//Person.h
#ifndef PERSON_H_
#define PERSON_H_
#include<string>
using std::string;
class Person{
private:
string firstname;
string lastname;
public:
Person(const char *fn="NoName", const char *ln="NoName"); //A
Person(const string &fn, const string &ln);
virtual ~Person(){}
};
class Gunslinger:virtual public Person{
private:
int notchnum;
public:
Gunslinger(const char*f="unknown",const char*n="unknown",int not=0);//B
virtual ~Gunslinger(){}
};
class PokerPlayer:virtual public Person{
public:
PokerPlayer(const char*fn="unknown", const char*ln="unknown");//C;
virtual ~PokerPlayer(){}
};
class BadDude:public Gunslinger,public PokerPlayer{
public:
BadDude(const char*fn="unknown", const char*ln="unknown", int notc=0);//D
};
#endif
//PersonDefinition.cpp
#include"Person.h"
#include<iostream>
#include<cstdlib>
using std::cout;
using std::endl;
using std::cin;
Person::Person(const char*fn, const char*ln):firstname(fn),lastname(ln){
}
Person::Person(const string &fn,const string &ln):firstname(fn),lastname(ln){
}
Gunslinger::Gunslinger(const char*fn,const char*ln, int not):Person(fn,ln),notchnum(not){
}
PokerPlayer::PokerPlayer(const char*fn,const char*ln):Person(fn,ln){
}
BadDude::BadDude(const char*fn, const char*ln, int notc):Person(fn,ln),PokerPlayer(fn, ln),Gunslinger(fn,ln,notc){
}
//PersonTest.cpp
#include<iostream>
#include "Person.h"
int main(){
Person a("Jack","Husain");
PokerPlayer b("Johnson","William",8);
Gunslinger c("Mensly","Sim");
}
So, here is the problem. The program above fails to compile with the default constructor with default value for all argument and throws an error message saying that "expected ',' or '...' before '!' token", but if I replace the default constructor in Line A,B,C,D with the form without argument, the program compiles and run successfully.Could anyone tell me why? Below is the error message.

You did not implement all the constructors. For instance, you declared a constructor PokerPlayer::PokerPlayer(char*, char*) but you are trying to create a PokerPlayer with PokerPlayer b("Johnson","William",8); (i.e. you never declared a constructor which takes the third argument). The declaration you want for that previous line to work is PokerPlayer::PokerPlayer(char*, char*, int);
Furthermore, you have the exact opposite problem when trying to declare a GunSlinger. Your GunSlinger class requires the third parameter and you are trying to declare it without that argument.
Even though your base class supports several types of constructors, each derived class must also have every constructor you wish to use on it explicitly declared/implemented (with the exception of the default constructor).
EDIT
Here is some semi-functional code:
class PokerPlayer : public Person
{
...
PokerPlayer(char* fname, char* lname, int val);
...
};
Implementation
PokerPlayer::PokerPlayer(char* fname, char* lname, int val) : Person(fname, lname, val)
{
// Anything else we should do...
}

Related

C++ class declaration after using it

I want to create method with an argument which links to Enemy which is declared later.
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
class Weapon{
public:
int atk_points;
string name;
string description;
void Attack(Entity target){
};
};
class Armor{
public:
int hp_points;
string name;
string description;
int block_chance;
};
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
I tried to search for answers, but nothing I found was helpful.
Here's error log:
prog.cpp:9:15: error: ‘Entity’ has not been declared
void Attack(Entity target){
The problem is that the compiler doesn't know what Entity is at the point where you have used as a parameter type. So you need to tell the compiler that Entity is a class type.
There are 2 ways to solve this both of which are given below:
Method 1
To solve this you need to do 2 things given below:
Provide a forward declaration for the class Entity.
Make the parameter of Attack to be a reference type so that we can avoid unnecessary copying the argument and also since we're providing a member function's definition instead of just declaration.
class Entity; //this is the forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v------------>target is now an lvalue reference
void Attack(const Entity& target){
};
};
Working demo
Method 2
Another way to solve this is that you can provide just the declaration for the member function Attack' inside the class and then provide the definition after the class Entity's definition as shown below:
class Entity; //forward declaration
class Weapon{
public:
int atk_points;
string name;
string description;
//------------------------------v----------->this time using reference is optional
void Attack(const Entity& target); //this is a declaration
};
//other code here as before
class Entity{
public:
int hp;
int atk;
string name;
vector<Weapon> weapons;
vector<Armor> armors;
};
//implementation after Entity's definition
void Weapon::Attack(const Entity& target)
{
}
Working demo
You can't.
You must declare it earlier. You can, however, define it later, in some circumstances.
To forward declare a class, write this before it is used:
class Entity;
In c++, such code cannot compile:
class A {
void fooa(B) {}
};
class B {
void foob(A) {}
};
However, such code can be compiled, we can change code in the way:
class A { };
class B { };
void fooa(A *, B) {}
void foob(B *, A) {}
It works and nothing is recursive.
So, I don't think change to reference is a good idea. The directly way to do that is just to use some trick. For example, change Entity to auto. Like that: void Attack(auto target).
What's more, with c++20, you can define a concept attackable and make Entity is attackable, I like it much.

Why am I getting a "no matching function" error?

Pretty new to C++, I was given an assignment that is basically about utilizing two different classes, however when creating my header files and c++ files and attempting to compile I get an error that reads no matching function for call to 'Owner::Owner()'. Since I am not super familiar with C++ yet I am assuming that this issue has something to do with my constructors and the way I am trying to call them, my assignment details what I think my issue is about but I am having trouble understanding exactly what needs to be done. I will provide the assignment details on the issue, as well as the code and compilation error below. Sorry for all the information I've just been stuck with this issue for a while and I can't seem to figure out a solution.
Transcribed Error
In constructor 'Dog::Dog(std::__cxx11::string, int)':
Dog.cpp:23:46: error: no matching function for call to 'Owner::Owner()' Dog::Dog(std::string unsetBreed, int unsetAge){
Assignment Details
Now you will write a program that consists of two classes, a Dog class and an Owner class. Their specification is shown in the UML diagram below. Notice that in our design, every Dog has an Owner class member. Class Owner is immutable, as mentioned above. An immutable class is just a class whose members cannot be changed(mutated) after an object was instantiated. Therefore, the Owner class does not have any setter methods. The Owner’s class attributes must be set at the time of creation(in the Owner’s constructor). You will call Owner’s constructor from inside Dog’s constructor. Do not forget to do it inside each constructor in class Dog.
Dog.h File
#ifndef DOG_H_INCLUDED
#define DOG_H_INCLUDED
#include <iostream>
#include "Owner.h"
class Dog {
//-----------------------//
private:
std::string breed;
int age;
Owner owner;
static int dogCount;
//-----------------------//
public:
Dog();
Dog(std::string, int);
std::string getBreed();
int getAge();
void setBreed(std::string);
void setAge(int);
void printDogInfo();
int getDogCount();
};
#endif // DOG_H_INCLUDED
Owner.h File
#ifndef OWNER_H_INCLUDED
#define OWNER_H_INCLUDED
#include <iostream>
class Owner {
//-----------------------//
private:
std::string name;
int age;
//-----------------------//
public:
Owner(std::string, int);
std::string getName();
int getAge();
//-----------------------//
};
#endif // OWNER_H_INCLUDED
Dog.cpp File
#include <iostream>
#include "Owner.cpp"
#include "Owner.h"
#include "Dog.h"
//---------------SETTERS------------------//
void Dog::setBreed(std::string dogBreed){dogBreed = breed;}
void Dog::setAge(int dogAge){dogAge = age;}
//--------------GETTERS------------------//
std::string Dog::getBreed(){return breed;}
int Dog::getAge(){return age;}
int Dog::getDogCount(){return dogCount;}
//--------------OTHERS-------------------//
Dog::Dog(std::string unsetBreed, int unsetAge){
Owner::Owner(std::string unsetName, int unsetOwnerAge);
Dog::setBreed(unsetBreed);
Dog::setAge(unsetAge);
}
void Dog::printDogInfo(){
Dog::getBreed();
Dog::getAge();
}
Owner.cpp File
#include <iostream>
#include "Owner.h"
#include "Dog.h"
//--------------GETTERS------------------//
int Owner::getAge(){return age;}
std::string Owner::getName(){return name;}
//--------------OTHERS-------------------//
Owner::Owner(std::string unsetName, int unsetOwnerAge){
Owner::getName();
Owner::getAge();
}
The problem here is that you don't have a constructor that receives 0 parameters.
You have 2 options:
1 - Define other constructor:
//header file
class Owner {
...
public:
Owner(std::string, int);
Owner();
...
};
//cpp file
...
Owner::Owner(){
name = "Jhon Doe";
age = 18;
}
...
2 - Define default params:
//header file
class Owner {
...
public:
Owner(std::string unsetName = "John Doe", int unsetAge = 18);
...
};
//cpp file
...
Owner::Owner(std::string unsetName = "John Doe", int unsetAge = 18);
Owner::getName();
Owner::getAge();
}
...
Note: I don't know why you are calling getter in the constructors.
Looks like your Owner class dosen't have a default constructor try including Owner::Owner() constructor.

forward declaration on c++ with a list inside

I have two clases Pet and Person
Here is the Person.h:
#ifndef PERSON_H
#define PERSON_H
#include <list>
class Pet;
class Person
{
public:
Person();
Person(const char* name);
Person(const Person& orig);
virtual ~Person();
bool adopt(Pet& newPet);
void feedPets();
private:
char* name_;
std::list<Pet> pets_;
};
#endif
And here is the Pet.h
#ifndef PET_H
#define PET_H
#include <list>
#include "Animal.h"
class Person;
class Pet : public Animal
{
public:
Pet();
Pet(const Pet& orig);
virtual ~Pet();
std::list<Pet> multiply(Pet& pet);
private:
std::string name_;
Person* owner_;
};
#endif
The problem that i have is this:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/list.tcc:129: error: invalid use of undefined type `struct Pet'
Person.h:13: error: forward declaration of `struct Pet'
I fixed trying to put this std::list<Pet>* pets_; but when i tried to call list functions always have a link problem. My question is how a have to include a list inside a class that contains objects from another class.
The standard requires that, except where explicitly stated, you use complete types with the library templates. This basically inhibits your design (where each object maintains by value a list of the other type).
You can work around this by using [smart] pointers (either a pointer to the container or container of pointers).

Error: Invalid base class C++

Could anyone, please, explain what can cause this error?
Error: Invalid base class
I've got two classes where one of them is derived from second:
#if !defined(_CGROUND_H)
#define _CGROUND_H
#include "stdafx.h"
#include "CGameObject.h"
class CGround : public CGameObject // CGameObject is said to be "invalid base class"
{
private:
bool m_bBlocked;
bool m_bFluid;
bool m_bWalkable;
public:
bool draw();
CGround();
CGround(int id, std::string name, std::string description, std::string graphics[], bool bBlocked, bool bFluid, bool bWalkable);
~CGround(void);
};
#endif //_CGROUND_H
And CGameObject looks like this:
#if !defined(_CGAMEOBJECT_H)
#define _CGAMEOBJECT_H
#include "stdafx.h"
class CGameObject
{
protected:
int m_id;
std::string m_name;
std::string m_description;
std::string m_graphics[];
public:
virtual bool draw();
CGameObject() {}
CGameObject(int id, std::string name, std::string description, std::string graphics) {}
virtual ~CGameObject(void);
};
#endif //_CGAMEOBJECT_H
I tried cleaning my project but in vain.
It is not valid to define an array (std::string m_graphics[]) without specifying its size as member of a class. C++ needs to know the size of a class instance in advance, and this is why you cannot inherit from it as C++ won't know at runtime where in the memory the members of the inheriting class will be available.
You can either fix the size of the array in the class definition or use a pointer and allocate it on the heap or use a vector<string> instead of the array.

C++ Inheritance - Running Parent Method in Child Class

My parent class, Course, has the method addStudent(Student s). My child class, BetterCourse, inherits from Course. Every time I try to run BetterCourse.addStudent(s), I get the following error:
error: no matching function for call to
‘BetterCourse::addStudent(Student (&)())’ note: candidates are: void Course::addStudent(Student)
I understand it's telling me addStudent() hasn't been defined in BetterCourse and that it's recommending I use the one present in the parent class, Course. This has me confused as the whole idea around inheritance is not needing to redefine inherited functions and variables.
Course is as follows:
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
class Course
{
protected:
string id;
string name;
public:
Course();
Course(string id, string name);
void addStudent(Student s);
};
Course::Course()
{
//code
}
Course::Course(string id, string name)
{
//code
}
void Course::addStudent(Student s)
{
//code
}
BetterCourse:
#include <iostream>
#include <string>
#include "Course.h"
using namespace std;
class BetterCourse : public Course
{
public:
BetterCourse(string id, string name) : Course(id,name){};
};
From your error it seems that you for the first time get to the ugliest part of C++.
This:
Student s();
Is function declaration - not object definition. s type is Student (*)() so when you call:
BetterCourse bc;
bc.addStudent(s);
You get your error - you don't have method to add functions returning Student.
Define Student in the following ways:
Student s;
Student s {}; // new C++11 way
Student s = Student(); //
It sounds like you're actually calling the function 'addStudent' with an inappropriate argument. Could you show the code that is actually calling addStudent on the BetterCourse object? It sounds like you're using a reference to the student instead of the student object itself.
you can not call BetterCourse.addStudent(s) you should create an object
BetterCourse obj;
obj.addStudent(s);
should work
If you want to call BetterCourse::addStudent(s) than declare addStudent(s) as static method