C++ Scope Operator in Derivation List - c++

I'm getting an error in WinImp.h that says 'Root' has not been declared. If I don't use the scope operator (class WinImp : public BaseDef) the error is error: expected class-name before '{' token). Anyone know why this is happening?
Root.h
class Root {
public:
class BaseDef {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
private:
#ifdef _WIN32
friend class WinImp;
#else
friend class NixImp;
#endif
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
Root.cpp
#include "Root.h"
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
WinImp.h
#ifdef _WIN32
#include "Root.h"
class WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
#endif
WinImp.cpp
#include "WinImp.h"
#ifdef _WIN32
void WinImp::foo() {
}
void WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return static_cast<BaseDef*>(new WinImp());
}
#endif

You are accessing BaseDef interfaces in Root, so they suppose to be public:
class BaseDef
{
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
In WinImp.cpp, foo(), bar() need return type and they are not inside Root scope, should be:
void WinImp::foo() { }
void WinImp::bar() { }

Fix WinImp.cpp to look like this:
#include "WinImp.h"
#ifdef _WIN32
// WinImp is not scoped within Root
void WinImp::foo() {
}
void WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return dynamic_cast<BaseDef*>(new WinImp());
}
#endif

Related

Call C++ virtual functions through C struct of function pointers

I'm creating a C-wrapper for a C++ class:
class IObject {
public:
virtual int getValue() const;
virtual ~IObject() = default;
};
class Object: public IObject {
public:
virtual int getValue() const { return 123; }
};
Inspired openh264's C API, I have the following code:
// object.h
#pragma one
#ifdef __cplusplus
class IObject {
public:
virtual int getValue() const = 0;
virtual ~IObject() = default;
};
extern "C" {
#else
typedef struct IObjectVtable IObjectVtable;
typedef IObjectVtable const* IObject;
struct IObjectVtable {
int (*getValue)(IObject*);
};
#endif
int makeObject(IObject**);
int freeObject(IObject*);
#ifdef __cplusplus
} // extern "C"
#endif
// object.cpp
#include "object.h"
class Object : public IObject {
public:
virtual int getValue() const override { return 123; }
};
extern "C" {
int makeObject(IObject** obj) {
*obj = new Object;
if (*obj == nullptr) {
return 1;
}
return 0;
}
int freeObject(IObject* obj) {
delete obj;
return 0;
}
}
In main.c, I use Object as follows:
#include <stdio.h>
#include "object.h"
int main() {
IObject* obj;
makeObject(&obj);
printf("%d\n", (*obj)->getValue(obj)); /** Calling getValue */
freeObject(obj);
return 0;
}
The code compiles and correctly prints "123", but I need to pass obj as an argument of getValue(). Is it possible to avoid this, i.e., simply call obj->getValue()?
According to the documentation, openh264 can do that, but I don't understand how/why it works:
ISVCDecoder *pSvcDecoder; //similar to IObject* obj;
WelsCreateDecoder(&pSvcDecoder); //similar to makeObject(&obj);
pSvcDecoder->Initialize(&sDecParam); //similar to obj->getValue();
// not (*obj)->getValue(obj)

Error"pure virtual method called",when this method has been override

I'm trying to practice "Observer Design Pattern". When I thought a abstract's pure virtual method has been override by it's derived class, a error occurred.
There is a observer which is an abstract class in a independent file:
#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H
Observer defined a pure virtual method "update" which overrides as follow:
#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H
And also there is a subject which is an abstract class too.The error "pure virtual method called" happened in "notify" method where I had marked.
From debug, it seems "notify" uses Observer's "update" rather than ConcreteObserver's.
However,in main function the _observers should stored pointers of ConcreteObservers which override "update".
#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H
And it has a derived class "ConcreteSubject":
#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H
The main function:
#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}
As I mentioned before, the _observers of ConcreteSubject's super class Subject should stored pointers of ConcreteObservers which override "update" already.
I don't understand why Observer's "update" still called.
Here is another strange thing.I make a small test has almost the same relationship of classes I showed.But no error occured.
class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}
The only difference is this code is in one file.
In the file of Subject.h you should be transfer below code to Subject.cpp:
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
Also you should be add class Observer; in top of Subject.h
#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};

How to write includes with Visitor Pattern? [Simple Example]

I can't seem to figure out how to write the includes of the Visitor Pattern with this simple example. No matter what I do I always end up with circular dependencies, but no other way makes sense.
Also I apologize for the different header guards (pragma vs. #ifndef), I was testing #pragma out and hadn't updated the files yet.
Client.cpp
#include "OneVisitor.h"
#include "DataStructure.h"
int main (int argc, char * argv [])
{
OneVisitor v;
DataStructure d;
}
DataStructure.h
#ifndef _DATA_STRUCTURE_H_
#define _DATA_STRUCTURE_H_
#include "ElementA.h"
class DataStructure {
public:
DataStructure (Visitor & v)
{
std::cout << "ACCEPTS";
a->accept(v);
};
private:
ElementA * a;
};
#endif
Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
#include "Visitor.h"
#include <iostream>
class Element {
public:
virtual void accept (Visitor & v) = 0;
void talk ()
{
std::cout << "ELEMENT TALKING";
};
};
#endif
ElementA.h
#pragma once
#include "Element.h"
#include "Visitor.h"
class ElementA : public Element {
public:
virtual void accept (Visitor & v) override
{
v.Visit(*this);
};
void talk ()
{
std::cout << "ELEMENT A TALKING";
};
};
Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
#include "ElementA.h"
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif
OneVisitor.h
#ifndef _ONE_VISITOR_H_
#define _ONE_VISITOR_H_
#include "Visitor.h"
class OneVisitor : public Visitor {
public:
virtual void Visit (ElementA & a) override
{
a.talk();
};
};
#endif
When I run this, I get the error "Visitor has not been declared" in Element.h, ElementA.h, ElementB.h. How can i get Visitor defined in these classes without causing circular dependencies?
A visitor is a very abstract concept, and it makes sense to template it in this case. Using templates allows us to get rid of circular dependencies, and simplify things considerably.
// Visitor.hpp
#pragma once
template<class T>
class Visitor {
public:
virtual void visit(T& item) = 0;
virtual ~Visitor() = default;
};
Now, if you want to have visitor for Element, you could just use Visitor<Element>:
// Element.hpp
#pragma once
#include "Visitor.hpp"
#include <iostream>
class Element
{
public:
virtual void accept(Visitor<Element>& v)
{
v.visit(*this);
}
virtual void talk() {
std::cout << "Element talking!\n";
}
virtual ~Element() = default;
};
Now that we have these things, we can also write a function to convert lambdas into visitors:
template<class T, class Func>
struct FunctionVisitor : public Visitor<T> {
Func func;
FunctionVisitor() = default;
FunctionVisitor(FunctionVisitor const&) = default;
FunctionVisitor(FunctionVisitor&&) = default;
FunctionVisitor(Func const& func)
: func(func)
{
}
void visit(T& item) override {
func(item);
}
};
template<class T, class Func>
FunctionVisitor<T, Func> makeVisitor(Func const& f) {
return FunctionVisitor<T, Func>(f);
}
Bringing it all together
This allows us to write nice code like this:
#include "Element.hpp"
#include "Visitor.hpp"
#include <vector>
class ElemA : public Element {
public:
void talk() override {
std::cout << "ElemA talking!\n";
}
};
class ElemB : public Element {
public:
void talk() override {
std::cout << "ElemB talking!\n";
}
};
class ElemC : public Element {
public:
void talk() override {
std::cout << "ElemC talking!\n";
}
};
void visitAll(std::vector<Element*>& elements, Visitor<Element>& visitor) {
for(auto e : elements) {
e.accept(visitor);
}
}
int main() {
std::vector<Element*> elements {
new ElemA(),
new ElemB(),
new ElemC()
};
auto talk = [](Element& e) { e.talk(); };
visitAll(elements, makeVisitor<Element>(talk));
}
By using a forward declaration of the class ElementA; in Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
// Just use a forward declaration of the class ElementA;
// NOTE1: The include of ElementA.h is not needed anymore.
// NOTE2: The visitor.h doesn't need to know what is defined
// in ElementA, only your .cpp needs, this is how forward
// declaration works.
class ElementA;
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif

'Cannot instantiate abstract class' although class shouldn't be abstract

So I have two classes. One has only purely virtual functions. THe other implements those functions and is derived from the first class.
I get that i cant instantiate the first class. But when I try to create an object of the second class it fails as well.
This is how my second class looks in general:
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
}
Implementation:
SecondClass::SecondClass()
{...}
SecondClass::~SecondClass(void)
{...}
void SecondClass::Foo()
{...}
void SecondClass::Bar()
{...}
This how I instantiate it and get the Error:
SecondClass mSecClass;
Where am I going wrong here?
FirstClass.h
class FirstClass
{
public:
FirstClass(void);
virtual ~FirstClass(void);
virtual void Foo() = 0;
virtual void Bar() = 0;
};
You need to define the ~FirstClass() destructor and leave out its constructor
class FirstClass
{
public:
virtual ~FirstClass(void) {} // or use C++11 = default syntax
virtual void Foo() = 0;
virtual void Bar() = 0;
};
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
};
SecondClass::SecondClass() {}
SecondClass::~SecondClass(void) {}
void SecondClass::Foo() {}
void SecondClass::Bar() {}
int main()
{
SecondClass mSecClass;
}
Live Example.
Define every function you declare, except for pure virtuals(virtual void foo() = 0).
try the below code:
#include<iostream>
using namespace std;
class FirstClass
{
public:
FirstClass()
{
//
}
virtual ~FirstClass();
virtual void Foo();
virtual void Bar();
};
FirstClass::~FirstClass()
{
//
}
void FirstClass::Foo()
{
//
}
void FirstClass::Bar()
{
//
}
class SecondClass : public FirstClass
{
public:
SecondClass();
virtual ~SecondClass(void);
void Foo();
void Bar();
};
SecondClass::SecondClass(){
//
}
SecondClass::~SecondClass(void)
{//
}
void SecondClass::Foo()
{//
}
void SecondClass::Bar()
{//
}
int main()
{
SecondClass name;
return 0;
}

C++ Have One Nested Class Inherit From Another Nested Class

I'm writing a cross-platform class hierarchy, and want to keep the platform dependent implementations in their own class (as opposed to having one class with #ifdefs). This is what I have so far, but the compiler is complaining that BaseDef is private. Any help with how I could keep this basic structure while getting it to compile would be greatly appreciated :-)
Edit: It would seem from here that this isn't possible. Any other way I could keep this general structure and still compile?
Root.h
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
Root.cpp
#include "Root.h"
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
WinImp.h
#ifdef _WIN32
#include "Root.h"
class WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
#endif
WinImp.cpp
#include "WinImp.h"
#ifdef _WIN32
Root::WinImp::foo() {
}
Root::WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return new Root::WinImp();
}
#endif
Your main problem is that BaseDef is private. That means that other classes (aside from Root itself) cannot access the BaseDef name. One way is to make BaseDef public. Alternatively you can make the derived classes (WinImp and NixImp) friends of Root so that they can access the BaseDef name. In addition Root cannot access the members of BaseDef so they need to be public or make Root a friend of BaseDef.
class Root {
private:
class BaseDef {
public:
// These need to be public so that Root can see them or Root needs to be a friend.
//Nothing else can see BaseDef though so this is safe.
virtual void foo() = 0;
virtual void bar() = 0;
};
class WinImp; // Forward declare the classes
friend class WinImp; // And then make them friends
class NixImp;
friend class NixImp;
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
// Since this is a nested class i made it Root::WinImp
class Root::WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
void Root::WinImp::foo() {}
void Root::WinImp::bar() {}
Root::BaseDef* Root::getImp() {
return new WinImp();
}
This method is not allowed according to the 2003 standard (11.4.p2) but in C++11 (same example) it is explicitly allowed (11.3.p2). However, clang (3.1 tested) accepts this even in 2003 mode. gcc (4.7.2 tested) accepts this (even in 2003 mode) so long as the derived classes are nested inside the same class but not if outside the class.
It's complaining that BaseDef is private...
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
So make it public...
class Root {
public:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
Footnote:
You're trying to avoid #ifdef, so get rid of this:
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
Instead, just use a single class:
class Imp;