As a requirement of an assignment for a data structures class, I have to get the following class hierarchy to work: http://www.brpreiss.com/books/opus4/
The source code is also provided, and right now I am simply trying to get stuff to compile. This has required re-organizing class definitions into their respective header files, moving template implementation into .inc files, and finishing bits of code which were not implemented. I have been making progress, but I am stuck on the following error (compiled with VC++):
1>main.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall Iterator::~Iterator(void)" (??1Iterator##UAE#XZ) referenced in function "public: virtual __thiscall NullIterator::~NullIterator(void)" (??1NullIterator##UAE#XZ)
I have tried all of the usual solutions (eliminating redundant include statements, cleaning the project and recompiling, etc.) and am not sure where to go. As was previously discussed, the consensus here seems to be that this code-base is really poorly designed. Nonetheless, the requirement of this assignment is to get this code working, and I am into deep to scrap it all together and start from scratch. If it
Here is the iterator class definition in iterator.h
#ifndef ITERATOR_H
#define ITERATOR_H
#include "object.h"
class Iterator
{
public:
virtual ~Iterator ();
virtual void Reset () = 0;
virtual bool IsDone () const = 0;
virtual Object& operator * () const = 0;
virtual void operator ++ () = 0;
};
class NullIterator : public Iterator
{
public:
NullIterator () {}
void Reset () {}
bool IsDone () const { return true; }
Object& operator * () const { return NullObject::Instance(); }
void operator ++ () {}
};
#endif
These are all of the other header files which are associated with iterator:
#ifndef CONTAINER_H
#define CONTAINER_H
#include "object.h"
#include "visitor.h"
#include "iterator.h"
#include "ownership.h"
class Container : public virtual Object, public virtual Ownership
{
protected:
unsigned int count;
Container () : count(0) {}
public:
virtual unsigned int Count () const { return count; }
virtual bool IsEmpty () const { return Count () == 0; }
virtual bool IsFull () const { return false; }
//virtual HashValue Hash () const;
virtual void Put (ostream&) const;
virtual Iterator& NewIterator () const { return *new NullIterator (); }
virtual void Purge () = 0;
virtual void Accept (Visitor&) const = 0;
};
#endif
Stack and Queue also inherit from Container, but it appears only stack makes use of Iterator:
#ifndef STACK_H
#define STACK_H
#include "linkList.h"
#include "container.h"
class Stack : public virtual Container
{
public:
virtual Object& Top () const = 0;
virtual void Push (Object&) = 0;
virtual Object& Pop () = 0;
};
class StackAsLinkedList : public Stack
{
LinkedList<Object*> list;
class Iter;
public:
StackAsLinkedList () : list() {}
~StackAsLinkedList() { Purge(); }
//
// Push, Pop and Top
//
void Push(Object& object);
Object& Pop() override;
Object& Top() const override;
int CompareTo(Object const& obj) const;
//
// purge elements from, and accept elements onto, the list
//
void Purge();
void Accept (Visitor&) const;
friend class Iter;
};
class StackAsLinkedList::Iter : public Iterator
{
StackAsLinkedList const& stack;
ListElement<Object*> const* position;
public:
Iter (StackAsLinkedList const& _stack) : stack(_stack) { Reset(); }
//
// determine whether iterator is pointing at null
//
bool IsDone() const { return position == 0; }
//
// overloaded dereference and increment operator
//
Object& operator*() const;
void operator++();
void Reset() { position = stack.list.Head(); }
};
#endif
If anyone has some insight, it would be much appreciated. I have been trying to solve this one error for the last few hours and haven't made any progress!
The error is a linking error which tells you that you have not provided a definition for the destructor:
virtual ~Iterator();
Which is being called through:
NullIterator::~NullIterator(void)
because NullIterator derives from Iterator class.
Solution is You should provide the definition for the Base class destructor.
Related
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
I have a C++ base class CAbstrInstruction and a large number of direct subclasses:
class CAbstrInstruction { /* ... */ };
class CSleepInstruction: public CAbstrInstruction { /* ... */ };
class CSetInstruction: public CAbstrInstruction { /* ... */ };
class CIfInstruction: public CAbstrInstruction { /* ... */ };
class CWhileInstruction: public CAbstrInstruction { /* ... */ };
// ...
There is also a CScriptWorker that exposes a public method execute:
class CScriptWorker
{
public:
void execute (const CAbstrInstruction *pI);
private:
void doSleep (const CSleepInstruction *pI);
void doSet (const CSetInstruction *pI);
void doIf (const CIfInstruction *pI);
void doWhile (const CWhileInstruction *pI);
// ...
};
The implementation of the execute method currently looks like this:
void CScriptWorker::execute (const CAbstrInstruction *pI)
{
const CSleepInstruction *pSleep =
dynamic_cast<const CSleepInstruction *>(pI);
if (pSleep != NULL)
{
doSleep (*pSleep);
return;
}
const CSetInstruction *pSet =
dynamic_cast<const CSetInstruction *>(pI);
if (pSet != NULL)
{
doSet (*pSet);
return;
}
const CIfInstruction *pIf =
dynamic_cast<const CIfInstruction *>(pI);
if (pIf != NULL)
{
doIf (*pIf);
return;
}
const CWhileInstruction *pWhile =
dynamic_cast<const CWhileInstruction *>(pI);
if (pWhile != NULL)
{
doWhile (*pWhile);
return;
}
/* ... */
}
This is very clumsy and takes O(log(n)) to invoke the correct private method. Is there
any design pattern or language construct that simplifies this?
Clarification: I could move the private execute methods do... into the instruction
classes. The execute method would simply become:
void execute (const CAbstrInstruction *pI) { pI->execute(); }
However, that's not what I want. Why not? Separation of concerns: The instances of CAbstrInstruction are just the description of what is do be done. They make up the Abstract Syntax Tree of the script. That's enough concern already. The CScriptWorker's concern is to actually do what's described by the instruction. CScriptWorker knows about the context the script is running in. CAbstrInstruction should not know about that.
Moving the implementation of the execute method into the subclasses of CAbstrInstruction could be the answer if things were simple. However, the OP explicitly stated the execute method should be kept separate in a CScriptWorker, to separate the concern of knowing about what is to be done (the instructions' job) from how it is to be done (the CScriptWorker's job). This may be achieved with double dispatch, also sometimes called the visitor pattern:
class IInstructionDispatchTarget
{
public:
virtual void onDispatch (const CSleepInstruction &instr) = 0;
virtual void onDispatch (const CSetInstruction &instr) = 0;
};
class CAbstrInstruction
{
public:
virtual void dispatch (IInstructionDispatchTarget &t) const = 0;
};
class CSleepInstruction: public CAbstrInstruction
{
public:
virtual void dispatch (IInstructionDispatchTarget &t) const override
{ t.onDispatch (*this); }
};
class CSetInstruction: public CAbstrInstruction
{
public:
virtual void dispatch (IInstructionDispatchTarget &t) const override
{ t.onDispatch (*this); }
};
class CScriptWorker: public IInstructionDispatchTarget
{
public:
void execute (const CAbstrInstruction *pI)
{ pI->dispatch (*this); }
virtual void onDispatch (const CSleepInstruction &instr) override
{
// do sleep
}
virtual void onDispatch (const CSetInstruction &instr) override
{
// do set
}
};
When execute gets called on the CScriptWorker, it invokes the dispatch method of the instruction. In return, the instruction invokes the onDispatch method on the dispatch target, using its specific this pointer and thus invoking the correct method.
The interface IInstructionDispatchTarget serves two purposes. On the one hand, it makes sure the instances of CAbstrInstruction do not need to know the CScriptWorker at all; all they need to know is the interface. On the other hand, it allows other dispatch targets to use the same mechanism, e.g. when traversing the instructions to optimize the AST.
If the presence of IInstructionDispatchTarget is considered unnecessary, things can be slightly simplified as shown by the answer by ROX.
CAbstrInstruction should define a pure virtual method (execute() in your example), which your child classes should override and implement.
As an example:
class CAbstrInstruction
{
/* ... */
virtual void execute() const = 0;
}
class CSleepInstruction
{
/* ... */
void execute() override const
{
/* your code here */
}
}
/* ... */
void CScriptWorker::execute (const CAbstrInstruction *pI)
{
pI->execute();
}
Inheritance is best used when the client does not need to know the concrete type of an object. You want to use a variant type, since you have a fixed number of known instructions, and your executor needs to know which kind of instruction it is executing. It's easiest to use std::variant, or boost::variant if you are pre-C++17.
#include <variant>
struct Set {};
struct If {};
struct While {};
using Instruction = std::variant<
Set,
If,
While
>;
#include <iostream>
struct Executor {
void operator()(Set const&) const { std::cout << "Set\n"; }
void operator()(If const&) const { std::cout << "If\n"; }
void operator()(While const&) const { std::cout << "While\n"; }
};
void execute(Instruction const& i) {
std::visit(Executor(), i);
}
Example:
#include <vector>
int main() {
for (auto const& i : std::vector<Instruction>{While(), If(), Set()}) {
execute(i);
}
}
Output:
While
If
Set
The visitor pattern works well if you have other classes that will the implement IInstructionVisitor interface. That ensures all those classes can handle the same set of Instruction classes.
If you don't have additional classes deriving from IInstructorVisitor then you can simplify it slightly:-
class CScriptWorker
{
public:
void execute (const CAbstrInstruction* pI)
{
pI->ResolveInstructionType(*this);
}
// Can be made friends of appropriate instruction classes or left public as you see fit
void doInstruction (const CSleepInstruction* pI);
void doInstruction (const CSetInstruction* pI);
void doInstruction (const CIfInstruction* pI);
void doInstruction (const CWhileInstruction* pI);
// note the name is now the same, name of the parameter should be enough to tell what's being done
// also I'd probably make these references not pointers
};
class CAbstrInstruction
{
public:
virtual void ResolveInstructionType (CScriptWorker& v) = 0;
};
class CSleepInstruction: public CAbstrInstruction
{
public:
void ResolveInstructionType (CScriptWorker& w) override { w.doInstruction (this); }
};
The slight advantages of the simplification are, slightly less code now, slightly less code to modify if a new instruction is added, you can choose names other than visit, visitor etc.
KSetBase.h base class , an interface
#ifndef HW6_GTUSETBASE_H
#define HW6_GTUSETBASE_H
class KSet;
#include <cstddef>
namespace TU {
template<typename T>
class KSetBase {
public:
virtual bool empty() const = 0;
virtual size_t size() const = 0; //int is not okay since unsigned also could be in.
//comparisons would be not working if that was case
//detailed
//https://stackoverflow.com/questions/1181079/stringsize-type-instead-of-int
virtual size_t max_size() const = 0;
virtual void insert(T first, T second) = 0; //cift dondurmesi gerekli
virtual void erase(T deleter) = 0;
virtual void clear() = 0;
virtual T find(T deneme) = 0;
virtual size_t count(T testle) = 0;
virtual T begin() = 0;
virtual T end() = 0;
protected:
~GTUSetBase() {
//do nothing
}
};
}
#endif //HW6_GTUSETBASE_H
KSet.h (derived class)
#include "KSetBase.h"
#ifndef HW6_GTUSET_H
#define HW6_GTUSET_H
#include <memory>
using namespace std;
namespace TU {
template<typename T>
class KSet : public KSetBase {
public:
bool empty() const;
size_t size() const;
size_t max_size() const;
void insert(T first);
void erase(T deleter);
void clear();
T find(T deneme);
size_t count(T testle);
T begin();
T end();
protected:
int hmany = 0;
shared_ptr<T> set_harmony;
};
}
#endif //HW6_GTUSET_H
I cant figure out what part of my code is wrong. I basically made a basic inheritance from interface class, which i implemented all functions in KSet.cpp. In theory nothing looks wrong but it gives 2 errors.
both in main.cpp and KSet.cpp
class KSet : public KSetBase {
Error line is this.
I checked #ifndef and #defines, i thought about using forward declaration but i cant seems to work that out.I am really stuck with this problem. I searched whole web about it , in the end there's always a big error on syntax or something that is visible , but i can't figure out on mine. It's very short and simple code.
KSetBase is a template class, if you inherit from it you must specify a template argument:
template<typename T>
class KSet : public KSetBase<T>
In addition, it seems you have a typo in the base class destructor.
I'm trying to implement the double dispatch pattern but I get a circular dependency that I can't resolve with forward declaration (as it was resolved in this problem link).
Below is an example of my problem:
header 1:
class Object
{
virtual void dispatchAdd(Collection& c) const = 0;
};
class Blockage: Object
{
virtual void dispatchAdd(Collection& c) const
{
c.add(*this);
}
};
class Boundary: Object
{
virtual void dispatchAdd(Collection& c) const
{
c.add(*this);
}
};
header 2:
class Collection
{
public:
void add(const Blockage& b)
{ ... }
void add(const Boundary& b)
{ ... }
...
private:
boost::unordered_set<Boundary> m_boundaries;
boost::unordered_set<Blockage> m_blockages;
}
I can't forward declare Boundary and Blockage in header 2, because I need a complete type to use boost::unordered_set. Any advice to resolve this problem?
Forward declare Collection in header 1 and move the implementations for dispatchAdd out of the header file and into the source file.
objects.h (i.e. "header 1"):
class Collection;
class Object
{
virtual void dispatchAdd(Collection& c) const = 0;
};
class Blockage: Object
{
virtual void dispatchAdd(Collection& c) const;
};
class Boundary: Object
{
virtual void dispatchAdd(Collection& c) const;
};
objects.cpp
#include "objects.h" // i.e. "header 1"
#include "collection.h" // i.e. "header 2"
void Blockage::dispatchAdd(Collection& c) const
{
c.add(*this);
}
void Boundary::dispatchAdd(Collection& c) const
{
c.add(*this);
}
I was just wondering if there was a way to create a c wrapper API for a c++ class that has inheritance.
Consider the following:
class sampleClass1 : public sampleClass{
public:
int get() { return this.data *2; };
void set(int data);
}
class sampleClass : public sample{
public:
int get() { return this.data; }
void set(int data) {this.data = data; }
}
class sample {
public:
virtual int get();
virtual void set(int data);
private:
int data;
}
How would I wrap the sampleClass1 to make it work in a c context ???
thanks,
First, your sample should really get a proper virtual dtor.
Next, just add one free function with C-binding for each function which is part of the interface, simply delegating:
"sample.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct sample sample;
sample* sample_create();
sample* sample_create0();
sample* sample_create1();
void sample_destroy(sample*);
int sample_get(sample*);
void sample_set(sample*, int);
#ifdef __cplusplus
}
#endif
"sample-c.cpp"
#include "sample.h" // Included first to find errors
#include "sample.hpp" // complete the types and get the public interface
sample* sample_create() {return new sample;}
sample* sample_create0() {return new sampleClass;}
sample* sample_create1() {return new sampleClass1;}
void sample_destroy(sample* p) {delete p;}
int sample_get(sample* p) {return p->get();}
void sample_set(sample* p, int x) {p->set(x);
"sample.hpp"
// Your C++ header here, with class definition
"sample.cpp"
#include "sample.hpp" // Included first to find errors
// Implement the class here