This question already has answers here:
Inheriting constructors
(8 answers)
Closed 4 years ago.
When I try to run my program it prints out
"error: no matching function for call to Dog::Dog(const char [4], const char [5])".
This occurs at line 60 and 61. Is it reading the arguments as a C-String? I should still be able to pass it into the constructor, can't I?
#include <iostream>
#include <string>
using namespace std;
#include <string>
class Pet
{
protected:
string type;
string name;
public:
Pet(const string& arg1, const string& arg2);
virtual void whoAmI() const;
virtual string speak() const = 0;
};
Pet::Pet(const string& arg1, const string& arg2): type(arg1), name(arg2)
{}
void Pet::whoAmI() const
{
cout << "I am an excellent " << type << " and you may refer to me as " << name << endl;
}
class Dog : public Pet
{
public:
void whoAmI() const; // override the describe() function
string speak();
};
string Dog::speak()
{
return "Arf!";
}
class Cat : public Pet
{
string speak();
// Do not override the whoAmI() function
};
string Cat::speak()
{
return "Meow!";
}
ostream& operator<<(ostream& out, const Pet& p)
{
p.whoAmI();
out << "I say " << p.speak();
return out;
}
int main()
{
Dog spot("dog","Spot");
Cat socks("cat","Socks");
Pet* ptr = &spot;
cout << *ptr << endl;
ptr = &socks;
cout << *ptr << endl;
}
Any help is greatly appreciated!
Pet has constructor taking 2 string, not Dog.
You might use Base constructor thanks to using (since C++11):
class Dog : public Pet
{
public:
using Pet::Pet;
void whoAmI() const; // override the describe() function
string speak();
};
Demo
Related
I need to implement one abstract class, three its concrete subclasses, class which goal to create one of this three classes instances and last class executor of three classes. Requirements are c++98, and not to use if/elseif/else to construct class instance, like i did in a Maker class method make Form. What mechanism i need to avoid if / elseif / else?
For example:
test.h
#ifndef TEST_H
#define TEST_H
#include <iostream>
class Executor {
private:
const std::string name;
public:
Executor(const std::string &name = "") {};
const std::string getname() const {return name;}
};
class BForm {
private:
const std::string _name;
public:
BForm(const std::string &name = "") : _name(name) {};
virtual ~BForm() {};
virtual void execute(const Executor &src) = 0;
const std::string getname() {return _name;}
virtual const std::string gettarget() = 0;
};
class Form1 : public BForm{
private:
std::string _target;
public:
Form1(const std::string &target = "") : BForm("form1"), _target(target) {};
virtual ~Form1() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form1 target:" << _target << std::endl;
}
virtual const std::string gettarget() {return _target;}
};
class Form2 : public BForm {
private:
std::string _target;
public:
Form2(const std::string &target = "") : BForm("form2"), _target(target) {};
virtual ~Form2() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form2 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};
class Form3 : public BForm {
private:
std::string _target;
public:
Form3(const std::string &target = "") : BForm("form3"), _target(target) {};
virtual ~Form3() {};
virtual void execute(const Executor &src) {
std::cout << src.getname() << " exec form3 target:" << _target << std::endl;
};
virtual const std::string gettarget() {return _target;}
};
class Maker {
public:
BForm *makeForm(const std::string &name, const std::string &target)
{
/* need to avoid */
if (name == "form1")
return new Form1(target);
else if (name == "form2")
return new Form2(target);
else
return new Form3(target);
}
};
#endif
main.cpp
#include "test.h"
int main() {
Maker maker;
BForm *form;
Executor exec("executor");
form = maker.makeForm("form1", "A");
std::cout << form->getname() << " " << form->gettarget() << std::endl;
form->execute(exec);
delete form;
return (0);
}
You could typedef a pointer to function and then use a map from string to this type (pointer to function). And then use your parameter with indexer syntax to access the correct pointer to function.
Here is an example:
#include <iostream>
#include <map>
// The class definitions with a virtual function hello() common to all
class Base { public: virtual void hello() = 0; };
class Derived1 : public Base { public: void hello() { std::cout << "Derived1"; } };
class Derived2 : public Base { public: void hello() { std::cout << "Derived2"; } };
// The object making functions
Base* Maker1() { return new Derived1; }
Base* Maker2() { return new Derived2; }
int main()
{
// In C++98, without auto, it's worthwhile to typedef complicated types.
// The first one is a function type returning a pointer to Base...
typedef Base* MakerT();
// ... the second one is a map type projecting strings to such function pointers
typedef std::map<std::string, MakerT*> StrToMakerT;
/// The actual map projecting strings to maker function pointers
StrToMakerT strToMaker;
// Fill the map
strToMaker["D1"] = &Maker1;
strToMaker["D2"] = &Maker2;
// user input
std::string choice;
// as long as output works, input works, and the user didn't say "Q":
while (std::cout << "Please input 'D1' or 'D2' or 'Q' for quit: "
&& std::cin >> choice
&& choice != "Q")
{
// Prevent adding new entries to the map foir unknown strings
if (strToMaker.find(choice) != strToMaker.end())
{
// Simply look the function up again, the iterator type is too
// cumbersome to write in C++98
Base* b = (*strToMaker[choice])();
b->hello();
std::cout << '\n';
delete b;
}
else
{
std::cout << "Didn't find your choice, try again.\n";
}
}
std::cout << "Thank you, good bye\n";
}
The first printable(e) is giving "entity" but for the next line, the program crashes. giving some characters. Let me know the error.
#include<iostream>
using namespace std;
class A
{
public:
virtual string getclassname() = 0;
};
class entity : public A
{
public:
string getclassname() override
{
cout << "entity" << endl;
}
};
class player : public entity
{
private:
string m_name2;
public:
player(const string& name2) // Creating a constructor
:m_name2(name2) {}
string getname()
{
return m_name2;
}
public:
string getclassname() override
{
cout << "player" << endl;
}
};
void printable(A* en)
{
cout << en->getclassname() << endl;
}
int main()
{
entity* e = new entity();
player* p = new player("bird");
printable(e);
printable(p);
}
Your getclassname() function doesn't return anything even though it promises it does. This results in undefined behaviour. You should not print, but instead compose a string:
string getclassname() override
{
return "player";
}
I have a class which accepts a pointer to another class and has a method read():
class B:
{
public:
......
void read(char * str);
......
};
class A
{
public:
A(B *bobj):b(bobj);
B* b;
void read (char * str);
..........
};
I invoke the object like below
A * aobj = new A(new B());
Now I should be able to access read method of both the classes like below:
char text[100];
b->read(text)
aobj->read(text)
The method read of both A and B class is coded to copy some values to the input array as provided.
How can I write MOCK method of the function to modify the argument to a specific value?
ON_CALL(*b, read(::testing::_)).WillByDefault(::testing::Return(outBuffer));
Gives me a compilation issue as read method cannot return a value by definition?
I have used Invoke function to achieve this. Here is a sample code.
If you use >=c++11 then, you can simply give a lambda to the Invoke function.
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::Mock;
using ::testing::_;
using ::testing::Invoke;
class actual_reader
{
public:
virtual void read(char* data)
{
std::cout << "This should not be called" << std::endl;
}
};
void mock_read_function(char* str)
{
strcpy(str, "Mocked text");
}
class class_under_test
{
public:
void read(actual_reader* obj, char *str)
{
obj->read(str);
}
};
class mock_reader : public actual_reader
{
public:
MOCK_METHOD1(read, void(char* str));
};
TEST(test_class_under_test, test_read)
{
char text[100];
mock_reader mock_obj;
class_under_test cut;
EXPECT_CALL(mock_obj, read(_)).WillOnce(Invoke(mock_read_function));
cut.read(&mock_obj, text);
std::cout << "Output : " << text << std::endl;
// Lambda example
EXPECT_CALL(mock_obj, read(_)).WillOnce(Invoke(
[=](char* str){
strcpy(str, "Mocked text(lambda)");
}));
cut.read(&mock_obj, text);
std::cout << "Output : " << text << std::endl;
}
I have this code:
#include <iostream>
#include <string>
#include <cstring>
class Animal
{
public:
Animal(const std::string &name) : _name(name)
{
}
virtual void Print() const = 0;
virtual ~Animal() {}
protected:
std::string _name;
};
class Dog : public Animal
{
public:
Dog(const std::string &name, const std::string &dogtype) : Animal(name), _dogtype(dogtype)
{
Print();
}
void Print() const
{
std::cout << _name << " of type " << _dogtype << std::endl;
}
private:
std::string _dogtype;
};
class Cat : public Animal
{
public:
Cat(const std::string &name, int weight) : Animal(name), _weight(weight)
{
Print();
}
virtual void Print() const
{
std::cout << _name << " of weight " << _weight << std::endl;
}
virtual ~Cat(){}
private:
int _weight;
};
class Tiger : public Cat
{
public:
Tiger(const std::string &name, int weight, double speed) : Cat(name, weight), _speed(speed)
{
Print();
}
void Print() const
{
std::cout << _name << " speed " << _speed << std::endl;
}
virtual ~Tiger(){std::cout << "Tiger's dtor" << std::endl;}
private:
int _speed;
};
int main()
{
Animal *a = new Tiger("theRealKing", 3, 40.5);
Cat *c = new Cat("silvester", 4);
memcpy(c, a, sizeof(Cat));
c->Print(); /// ------------------------
delete a;
delete c;
return 0;
}
in the line : c->Print():
the line before that c became a tiger so why does it print me this line :
Ross with speed 135081
insted of
Ross with speed 3
why there is a memory problem ?
why does it call the print method of tiger and not of cat ?
It doesn't work together.
Using memcpy on these objects produces undefined behavior, the Standard permits anything to happen.
It isn't inheritance per se that is causing you problems, but the presence of virtual member functions or custom constructor/destructor. These make your objects lose the trivially-copyable classification that is required when using memcpy.
Your class isn't trivially-copyable for a second reason -- it contains a member of type std::string which is not trivially-copyable.
In practical terms, when you perform a bitwise copy of a std::string subobject, you end up with two pointers to the same memory, and both string objects will try to free this pointer. That will crash your program. If using memcpy on a v-table hasn't done so earlier.
But when you mix in optimizations, even weirder things can happen. That's what undefined behavior means.
You should avoid using memcpy for objects in c++, use the copy constructor instead.
Say I have the following classes in C++, and I want to inspect their inheritance:
Vehicle
Motorcar is a Vehicle
Aircraft is a Vehicle
Biplane is an Aircraft is a Vehicle
Helicopter is an Aircraft is a Vehicle.
I want to write a method getClassLineage() to do the following:
Biplane b;
cout << b.getClassLineage() << endl; // prints "Vehicle--Aircraft--Biplane"
Helicopter h;
cout << h.getClassLineage() << endl; // prints "Vehicle--Aircraft--Helicopter"
Motorcar m;
cout << m.getClassLineage() << endl; // prints "Vehicle--Motorcar"
It seems like there should be a simple recursive way to do this by writing it once in the super-class, without duplicating an essentially identical method in every single one of the derived classes.
Assume we're willing to declare (pseudocode)Helicopter.className = "Helicopter" and
typedef Aircraft baseclass in each of the derived classes, but trying to avoid copying and pasting getClassLineage().
Is there an elegant way to write this?
(Thank you for your thoughts!)
Solution 1
IF you're okay with the decorated name, then you can write a free function template:
struct Vehicle {};
struct Aircraft : Vehicle { typedef Vehicle super; };
struct Helicopter : Aircraft { typedef Aircraft super; };
template<typename T>
string getClassLineage()
{
static string lineage = string(typeid(T).name()) +" - " + getClassLineage<typename T::super>();
return lineage;
}
template<>
string getClassLineage<Vehicle>()
{
static string lineage = string(typeid(Vehicle).name());
return lineage;
}
int main() {
cout << getClassLineage<Helicopter>() << endl;
return 0;
}
Output (decorated names):
10Helicopter - 8Aircraft - 7Vehicle
See at ideone: http://www.ideone.com/5PoJ0
You can strip off the decoration if you want. But it would be compiler specific! Here is a version that makes use of remove_decoration function to strip off the decoration, and then the output becomes :
Helicopter - Aircraft - Vehicle
By the way, as I said, the implementation of remove_decoration function is a compiler specific; also, this can be written in more correct way, as I don't know all cases which GCC considers, while mangling the class names. But I hope, you get the basic idea.
Solution 2
If you're okay with redefining the function in each derived class, then here is a simple solution:
struct Vehicle
{
string getClassLineage() const { return "Vehicle"; }
};
struct Aircraft : Vehicle
{
string getClassLineage() const { return Vehicle::getClassLineage()+" - Aircraft"; }
};
struct Helicopter : Aircraft
{
string getClassLineage() const { return Aircraft::getClassLineage()+" - Helicopter "; }
};
int main() {
Helicopter heli;
cout << heli.getClassLineage() << endl;
return 0;
}
Output:
Vehicle - Aircraft - Helicopter
See output at ideone: http://www.ideone.com/Z0Tws
If you want a recursive-like approach you can do it with virtual functions and explicit scoped function calls:
struct vehicle {
virtual std::string lineage() const { return "vehicle"; }
};
struct aircraft : vehicle {
typedef vehicle base;
virtual std::string lineage() const { return base::lineage() + "--aircraft"; }
};
struct biplane : aircraft {
typedef aircraft base;
virtual std::string lineage() const { return base::lineage() + "--biplane"; }
};
struct nieuport17 : biplane {
typedef biplane base;
virtual std::string lineage() const { return base::lineage() + "--nieuport17"; }
};
int main() {
biplane b;
aircraft const & a = b;
std::cout << a.lineage() << std::endl;
}
How does it work? When you call v.lineage() as it is a virtual function it the dynamic dispatch will make its way into biplane::lineage() as that is the actual type of the object. Inside that function there is a qualified call to its parent's lineage() function. Qualified calls do not use the dynamic dispatch mechanism, so the call will actually execute at the parents level. Basically this is what is going on:
a.lineage() -- dynamic dispatch -->
---> biplane::lineage()
\__ airplane::lineage()
\__ vehigcle::lineage()
<-- std::string("vehicle")
<-- std::string("vehicle") + "--airplane"
<-- std::string("vehicle--airplane") + "--biplane"
<--- std::string( "vehicle--airplane--biplane" )
[...]but trying to avoid copying and pasting getClassLineage().
As far as I know, that's not possible. C++ doesn't have reflection in and of itself, so the programmer has to do the work himself. The following C++0x version works under Visual Studio 2010, but I can't say for other compilers:
#include <string>
#include <typeinfo>
#include <iostream>
class Vehicle{
public:
virtual std::string GetLineage(){
return std::string(typeid(decltype(this)).name());
}
};
class Aircraft : public Vehicle{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Vehicle::GetLineage();
return lineage;
}
};
class Biplane : public Aircraft{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Aircraft::GetLineage();
return lineage;
}
};
class Helicopter : public Aircraft{
public:
virtual std::string GetLineage(){
std::string lineage = std::string(typeid(decltype(this)).name());
lineage += " is derived from ";
lineage += Aircraft::GetLineage();
return lineage;
}
};
int main(){
Vehicle v;
Aircraft a;
Biplane b;
Helicopter h;
std::cout << v.GetLineage() << std::endl;
std::cout << a.GetLineage() << std::endl;
std::cout << b.GetLineage() << std::endl;
std::cout << h.GetLineage() << std::endl;
std::cin.get();
return 0;
}
Output:
class Vehicle *
class Aircraft * is derived from class Vehicle *
class Biplane * is derived from class Aircraft *
class Helicopter * is derived from class Aircraft *
The output is slightly different at ideone, it drops the asterisk and decorates the name with a P at the beginning for pointer, but it works. Fun fact: trying to use typeid(decltype(*this)).name() crashed VS2010's compiler for me.
You need a static field to store the lineage, and each class will have its own lineage appended in its own static field.
If you are thinking about using typeid() or something like that, which is more complex but would avoid the repetition of the getClassLineage() method, remember that the name field attribute is annoyingly (the reason for this is beyond me) not the true name of the class, but a string that can be that name or any kind of mangled name (i.e., undefined representation).
You could easily apply a recursive aproach as the one you suggest if we were using Python or any other prototype-based programming language, in which inheritance is implemented by delegation, and thus the "inheritance path" can be followed.
#include <iostream>
#include <string>
class Vehicle {
public:
static const std::string Lineage;
Vehicle() {}
virtual ~Vehicle() {}
virtual const std::string &getClassLineage()
{ return Vehicle::Lineage; }
};
class Motorcar : public Vehicle {
public:
static const std::string Lineage;
Motorcar() {}
virtual ~Motorcar() {}
virtual const std::string &getClassLineage()
{ return Motorcar::Lineage; }
};
class Helicopter : public Vehicle {
public:
static const std::string Lineage;
Helicopter() {}
virtual ~Helicopter() {}
virtual const std::string &getClassLineage()
{ return Helicopter::Lineage; }
};
class Biplane : public Vehicle {
public:
static const std::string Lineage;
Biplane() {}
virtual ~Biplane() {}
virtual const std::string &getClassLineage()
{ return Biplane::Lineage; }
};
const std::string Vehicle::Lineage = "Vehicle";
const std::string Motorcar::Lineage = "Vehicle::Motorcar";
const std::string Helicopter::Lineage = "Vehicle::Helicopter";
const std::string Biplane::Lineage = "Vehicle::Biplane";
int main()
{
Biplane b;
std::cout << b.getClassLineage() << std::endl; // prints "Vehicle--Aircraft--Biplane"
Helicopter h;
std::cout << h.getClassLineage() << std::endl; // prints "Vehicle--Aircraft--Helicopter"
Motorcar m;
std::cout << m.getClassLineage() << std::endl; // prints "Vehicle--Motorcar"
return 0;
}
#include <iostream>
#include <ios>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <list>
#include <sstream>
using namespace std;
static const char *strVehicle = "Vehicle";
static const char *strMotorcar = "Motorcar";
static const char *strHelicopter = "Helicopter";
class Vehicle
{
private:
const char *ClassName;
protected:
int Lineage;
list<const char *> MasterList;
public:
Vehicle(const char *name = strVehicle)
{
MasterList.push_back(name);
}
virtual ~Vehicle() {}
virtual int getClassLineage() const
{
return Lineage;
}
string getName() const
{
list<const char *>::const_iterator it = MasterList.begin();
ostringstream ss( ios_base::in | ios_base::out );
while(it != MasterList.end())
{
ss << *(it++);
if(it != MasterList.end())
ss << " --> ";
}
ss << endl;
ss << ends;
return ss.str();
}
};
class Motorcar : public Vehicle
{
private:
const char *ClassName;
public:
Motorcar(const char *name = strMotorcar)
{
MasterList.push_back(name);
}
virtual ~Motorcar() {}
using Vehicle::getClassLineage;
using Vehicle::getName;
};
class Helicopter : public Vehicle
{
private:
const char *ClassName;
public:
Helicopter(const char *name = strHelicopter)
{
MasterList.push_back(name);
}
virtual ~Helicopter() {}
using Vehicle::getClassLineage;
using Vehicle::getName;
};
int _tmain(int argc, _TCHAR* argv[])
{
Helicopter h;
Motorcar m;
wcout << "Heli: " << h.getName().c_str() << endl;
wcout << "Motorcar: " << m.getName().c_str() << endl;
return 0;
}
If using typeid you don't need to hardcode strings (class' names). Solution for your problem could be:
#include <iostream>
#include <typeinfo>
using namespace std;
class Vehicle
{
public:
Vehicle();
string GetClassLineage(){return strName;}
protected:
string strName;
};
Vehicle::Vehicle() : strName(typeid(*this).name())
{
// trim "class "
strName = strName.substr(strName.find(" ") + 1);
}
class Motorcar : public Vehicle
{
public:
Motorcar();
};
Motorcar::Motorcar()
{
string strMyName(typeid(*this).name());
strMyName = strMyName.substr(strMyName.find(" ") + 1);
strName += " -- ";
strName += strMyName;
}
int main()
{
Motorcar motorcar;
cout << motorcar.GetClassLineage() << endl;
return 0;
}
Output:
Vehicle -- Motorcar