error: no ‘’ member function declared in class '' - c++

I'm trying to create a class containing a virtual function, which i would like to inherit in two child classes.
I know some people already asked this (here and there for example), but i couldn't understand the answers.
So i made a simplified example code of what i'm trying :
//Mother .h file
#ifndef _MOTHER_H_
#define _MOTHER_H_
#include <iostream>
class Mother
{
protected :
std::string _name;
public:
Mother(std::string name);
~Mother();
virtual std::string getName() = 0;
};
#endif
//Mother .cpp file
#include "Mother.h"
Mother::Mother(std::string name)
{
this->_name = name;
}
Mother::~Mother()
{
}
//Child.h file
#ifndef _CHILD_H_
#define _CHILD_H_
#include "Mother.h"
class Child : public Mother
{
private :
std::string _name;
public:
Child(std::string name);
~Child();
};
#endif
//Child .cpp file
#include "Mother.h"
#include "Child.h"
Child::Child(std::string name) : Mother(name)
{
this->_name = name;
}
Child::~Child()
{
}
std::string Mother::getName()
{
return this->_name;
}
Here is my main.cpp file :
//Main.cpp file
#include "Child.h"
int main()
{
Child l("lol");
std::cout << l.getName() << std::endl;
Mother& f = l;
std::cout << f.getName() << std::endl;
return 0;
}
Here's what the compilator says :
(compiling with g++ *.cpp -W -Wall -Wextra -Werror)
main.cpp: In function ‘int main()’:
main.cpp:5:9: error: cannot declare variable ‘l’ to be of abstract type‘Child’
In file included from main.cpp:1:0:
Child.h:8:7: note: because the following virtual functions are pure within ‘Child’:
In file included from Child.h:6:0,
from main.cpp:1:
Mother.h:14:23: note: virtual std::string Mother::getName()
What am i doing wrong ?
(sorry if i made some english mistakes, i am not a native speaker).

In Mother's declaration you have:
virtual std::string getName() = 0;
This is not just a virtual, but a pure virtual. The distinction between a virtual and a pure virtual is that the pure variety must have an override implemented in a derived class, even if you have provided an implementation in the base class. For example:
class Foo
{
public:
virtual void DoIt() = 0 {}; // pure virtual. Must be overridden in the derived class even though there is an implementation here
};
class Bar : public Foo
{
public:
void DoIt(); // override of base
};
void Bar::DoIt()
{
// implementation of override
}
You can't instantiate a class with un-implemented pure virtual methods. If you try, you will get a compiler error:
int main()
{
Foo f; // ERROR
Bar b; // OK
}
And that is exactly what you tried to do. You declared getName() to be pure virtual in
Mother, but you did not override it in Child. Then you tried to instantiate a Child
int main()
{
Child l("lol");
Which resulted in the compiler error.
To fix it, provide an override of getName() in the Child class.

You class child should override getName() method as it is pure virtual defined in class mother
Seems typo to me.. as std::string Mother::getName() is defined in child.cpp..
std::string Child::getName()
{
return this->_name;
}

The pure virtual function in your base class Mother does not make sense from an OOP perspective, it is a common trait in all children so the same function could be used. There is no need to override it.
struct Person
{
Person(std::string name) : _name(name) {}
std::string _name;
std::string getName() {return _name; }
};
struct Mother : Human
{
Mother(std::string name) : Person(name) {}
};
struct Child : Human
{
Child(std::string name) : Person(name) {}
};

Related

Visitor Pattern Error(use undefined type)

I am studying visiting patterns. However, the following error occurs. not defined.
The cat class only has its own name and age.
agevisitor and namevisitor, which inherit Visitor interface, output age and name.
I tried forward declaration, but the error of C2027 appears as it is. help me :(
that's my code
#include <iostream>
using namespace std;
class Visitor;
class Cat
{
public:
Cat(string name, int age) : name_(name), age_(age) {}
void Speak() {
cout << "meow" << endl;
}
void Accept(Visitor* visitor) {
cout << "use implementation of visitor" << endl;
visitor->visit(this); // #undefined type error
}
public:
string name_;
int age_;
public:
friend class AgeVisitor;
friend class NameVisitor;
};
class Visitor
{
public:
virtual void visit(Cat* cat) {}
};
class AgeVisitor : public Visitor
{
public:
virtual void visit(Cat* cat) {
cout << "cat is " << cat->age_ << "years old" << endl;
}
};
class NameVisitor : public Visitor
{
public:
virtual void visit(Cat* cat) {
cout << "cat's name is " << cat->name_ << endl;
}
};
int main()
{
Cat* first_cat = new Cat{ "kitty", 5 };
Visitor* age_visitor = new AgeVisitor();
first_cat->Accept(age_visitor);
}
Severity Code Description Project File Line Suppression State
Error C2027 use of undefined type 'Visitor' DesignPattern C:\Users\sueng\source\repos\DesignPattern\DesignPattern\DesignPattern.cpp 18
In case of circular dependency like in the Visitor pattern, ideally you should first decompose your code into headers and sources. This is because forward declared classes have incomplete type, so you can use pointers and references to them, you can also use them as return types, but you can't use any of their methods or create an actual instance either on the stack or dynamically, because the class layout is not known at the time.
Example Cat.hpp:
class Visitor;
class AgeVisitor; // needed just for the friend declaration
class NamedVisitor;
class Cat
{
public:
Cat(string name, int age);
void Accept(Visitor* visitor); // note that we only declare the class Cat, no methods definitions
public:
string name_;
int age_;
public:
friend class AgeVisitor;
friend class NameVisitor;
};
Then Visitor.h and similar in case of NamedVisitor.h etc ... :
class Cat;
class Visitor
{
public:
virtual void visit(Cat* cat);
};
And then in Cat.cpp you can include the headers with the visitors definitions which allows you to use their methods:
#include "Cat.hpp"
#include "Visitor.hpp"
Cat::Cat(string name, int age): name_(name), age_(age) {}
void Cat::Accept(Visitor* visitor) {
cout << "use implementation of visitor" << endl;
visitor->visit(this); // now you can use it, because Visitor class declaration is available
}
Alternatively you can copy-paste all the code in the presented order to your main.cpp but it's a bad habit. Live demo with everything copy-pasted in 1 source.
Forward declaration of a class without declaring its methods allows only to use the class name in the places which don't need information about the methods of the class. If you use methods (even implicitly, such as calling constructor for the local variable) you need to declare them forward also. E.g. the following code will not compile:
class A;
class B
{
public:
B();
};
class C
{
public:
void Run()
{
A* pa; // ok, forward class declaration is enough to declare pointers
A a; // compile error, since here we call ctor, but we haven't declared it
B b; // ok, we declared ctor
}
};
// can be in a different file
B::B()
{}

C++ : calling an abstract base class constructor / undefined symbol in shared object

I am trying to use abstract classes and I met some problems when defining constructors of derived class. I wrote the following code, based on the answer to this question.
#include <string>
#include <iostream>
class ICommand {
private:
ICommand();
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual void callMe();
virtual void callMe2();
};
class MyCommand : public ICommand {
public:
int x;
MyCommand(const std::string& name) : ICommand(name) { }
MyCommand(const std::string& name, int x) : ICommand(name), x(x) { }
void callMe() {
std::cout << name << "\n";
}
void callMe2() {
std::cout << name << x << "\n";
}
};
void f(std::string name) {
MyCommand A(name);
A.callMe();
}
This compiles without error. However my aim is to build a .so for a R package). In the R installation process, the .so is build without error, with clang++ -shared, but then there is a verification step which produces
unable to load shared object '/path/object.so':
/path/object.so: undefined symbol: _ZTI8ICommand
I've met this kind of problem before, and there are workarounds — not calling Icommand(name) is fairly simple, but I want to understand what is happening there, and, if possible, how to avoid the workaround.
Thanks in advance for your thoughts.
Answer
For the convenience of future readers: the only necessary change here is to replace the definition of virtual functions in the abstract class by
virtual void callMe() = 0;
virtual void callMe2() = 0;
which makes them pure virtual functions. Why this settles the problem totally beats me.
With the:
class MyClass {
private:
MyClass();
};
You are deleting a default constructor. If you want to call a default constructor then (declare or) define or don't define one but don't delete it. Your derived class default constructor will call the base class default constructor:
#include <string>
#include <iostream>
#include <memory>
class ICommand {
public:
std::string name;
ICommand() : name("The name") { std::cout << "Default base class constructor." << std::endl; }
virtual void callMe() = 0;
};
class MyCommand : public ICommand {
public:
MyCommand(){ std::cout << "Default derived class constructor." << std::endl; };
void callMe() override {
std::cout << name << std::endl;
}
};
void f2(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>();
p->callMe();
}
int main(){
f2("asdasd");
}
Part 2:
If you are trying to use the above classes in a polymorphic way then make your ICommand member functions pure virtual:
virtual void callMe() = 0;
virtual void callMe2() = 0;
Modify the void f function to:
void f(const std::string& name) {
std::shared_ptr<ICommand> p = std::make_shared<MyCommand>(name);
p->callMe();
}
Live example on Coliru.
class ICommand {
private:
ICommand() = default;
public:
const std::string name;
ICommand(const std::string& name) : name(name) { }
virtual ~ICommand() = default;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};

C++ unable to use super class' methods?

I feel stupid right now, haven't been doing C++ in ages, can't understand what's wrong... However I got this following class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
private:
std::string m_name;
};
And now I'm inheriting a simple class out of it:
#include "NamedObject.h"
enum eTeam { eAttacker, eDefender, eSpectator, eNone };
class Player : public NamedObject
{
public:
Player();
virtual ~Player();
virtual void printName();
virtual eTeam getTeam() const { return m_team };
virtual void setTeam(const eTeam team) { m_team = team };
private:
std::string m_name;
eTeam m_team;
};
However, I am unable to use player->setName("blabla") from my main.cpp? Here's the main file:
#include "Player.h"
int main()
{
Player* p1 = new Player();
p1->setName("Name Changed!")
p1->printName(); // prints "Unnamed" since I declared that in default ctor
return 0;
}
I'm not getting any errors, everything runs up well, the name just doesn't simply change. Also, I got all of the constructors and destructors, as well as my printName-method working perfectly, and the problem is not within them.
What you see is that setName modifies the m_name in the parent class and printName prints out the m_name of the derived class because you're redeclaring std::string m_name; in the derived class.
Remove the declaration from the derived class and mark m_name as protected member in the parent class:
#include <string>
class NamedObject
{
public:
NamedObject();
virtual ~NamedObject();
virtual std::string getName() const { return m_name };
virtual void setName(const std::string name) { m_name = name };
protected:
std::string m_name;
};
You could also keep m_name private and use the method getName() instead, as suggested by moswald.
You created another different variable m_name in your derived class that shadowed the one in the parent class.
I can see that must not be your real code.
Your derived/super class is redeclaring m_name. Probably not what you mean to do;)

C++ abstract base class constructors/destructors - general correctness

I would like to have a C++ Interface that must be overridden (if this is possible) when inherited. So far, I have the following:
class ICommand{
public:
// Virtual constructor. Needs to take a name as parameter
//virtual ICommand(char*) =0;
// Virtual destructor, prevents memory leaks by forcing clean up on derived classes?
//virtual ~ICommand() =0;
virtual void CallMe() =0;
virtual void CallMe2() =0;
};
class MyCommand : public ICommand
{
public:
// Is this correct?
MyCommand(char* Name) { /* do stuff */ }
virtual void CallMe() {}
virtual void CallMe2() {}
};
I have purposely left how I think the constructor/destructor's should be implemented in ICommand. I know if I remove the comments, it will not compile. Please could someone:
Show me how to declare the constructor/destructor's in ICommand and how they are meant to be used in MyCommand
Have I set things up correctly in ICommand so that MyCommand must override CallMe and CallMe2.
C++ does not allow for virtual constructors. A simple implementation (without the virtual constructor) would look something like this:
class ICommand {
public:
virtual ~ICommand() = 0;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};
ICommand::~ICommand() { } // all destructors must exist
Note that even a pure virtual destructor must be defined.
A concrete implementation would look exactly like your example:
class MyCommand : public ICommand {
public:
virtual void callMe() { }
virtual void callMe2() { }
};
You have a couple of options for the constructor. One option is to disable the default constructor for ICommand, so that subclasses will have to implement a constructor that calls your ICommand constructor:
#include <string>
class ICommand {
private:
const std::string name;
ICommand();
public:
ICommand(const std::string& name) : name(name) { }
virtual ~ICommand() = 0;
virtual void callMe() = 0;
virtual void callMe2() = 0;
};
ICommand::~ICommand() { } // all destructors must exist
A concrete implementation would now look something like this:
class MyCommand : public ICommand {
public:
MyCommand(const std::string& name) : ICommand(name) { }
virtual void callMe() { }
virtual void callMe2() { }
};
I know this one is old, but it is still my first hit on this issue. This is how I would do it.
Interface header foo.h:
#pragma once
#include <memory>
enum class Implementations {Simple, Fancy};
class Foo
{
public:
using Ptr = std::unique_ptr<Foo>;
virtual ~Foo() = default;
virtual void do_it() = 0;
};
Foo::Ptr create_foo(Implementations impl); // factory
Yes I know that "pragma once" is strictly speaking not standard, but it works for me.
Note that nothing is implemented here. There is no constructor: an abstract class can not be instantiated. You get a pointer to the interface through the factory. For the virtual function calls to work, they must be called through a pointer. The virtual destructor is defaulted because it doesn't have to do anything special except polymorphing to the implementation. The factory is a free function. No need to try to make it a static member or something like that. This is not java.
Interface foo.cpp:
#include "foo.h"
#include "foo_impl.h"
Foo::Ptr create_foo(Implementations impl)
{
switch (impl)
{
case Implementations::Simple:
return std::make_unique<Simple_foo>();
case Implementations::Fancy:
return std::make_unique<Fancy_foo>();
default:
return nullptr;
}
}
Here the factory is implemented. Notice that the factory has to know the implementation(s). That is why we don't implement it inline: if it was inline, the interface header would have to include the implementation header, and through it, knowledge of the implementation would "leak out" to the callsite.
The implementation header foo_impl.h:
#pragma once
#include "foo.h"
class Simple_foo : public Foo
{
void do_it() override;
};
class Fancy_foo : public Foo
{
void do_it() override;
};
Nothing special, just override the virtual functions of the interface. Because this exaple is simple, I put both implementations in the same files. In real applications that will be different.
The implementation foo_impl.cpp:
#include "foo_impl.h"
#include <iostream>
void Simple_foo::do_it()
{
std::cout << "simple foo\n";
}
void Fancy_foo::do_it()
{
std::cout << "fancy foo\n";
}
Just implement the functions.
The main.cpp:
#include "foo.h"
int main()
{
auto sf = create_foo(Implementations::Simple);
sf->do_it();
auto ff = create_foo(Implementations::Fancy);
ff->do_it();
return 0;
}
Through the enum we can select the implementation we want. The pointers are of type Foo::Ptr, an alias for std::unique_ptr<Foo>. The callsite has no knowledge of the implementation at all, only the interface.
The output will be as expected:
simple foo
fancy foo

Stopping or Blocking Inheritance in C++

I would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,