how to use struct in a class - c++

lifeform.h
class lifeform
{
public:
struct item;
void buyItem(item &a);
//code..
};
lifeform.cpp
struct lifeform::item
{
std::string type,name;
bool own;
int value,feature;
item(std::string _type,std::string _name,int _value,int _feature):type(_type), name(_name),value(_value),feature(_feature)
{
own=false;
}
};
lifeform::item lBoots("boots","Leather Boots",70,20);
void lifeform::buyItem(item &a)
{
if(a.own==0)
{
inventory.push_back(a);
a.own=1;
addGold(-a.value);
std::cout << "Added " << a.name << " to the inventory.";
if(a.type=="boots")
{
hp-=inventory[1].feature;
inventory[1]=a;
std::cout << " ( HP + " << a.feature << " )\n";
maxHp+=a.feature;
hp+=a.feature;
}
}
there is no error so far but when i wanna use them in main.cpp like this
#include "lifeform.h"
int main()
{
lifeform p;
p.buyItem(lBoots);
}
compiler says me [Error] 'lBoots' was not declared in this scope but i declared it class am i missing something?

To use your lifeform::item lBoots you need to declare it in main:
#include "lifeform.h"
extern lifeform::item lBoots; // <-- you need this.
int main()
{
lifeform p;
p.buyItem(lBoots);
}
Or alternatively you should place extern lifeform::item lBoots; in your lifeform.h.

Related

C++ : custom vtable implementation does not work

I'm trying to implement a custom vtable to better understand a concept of virtual tables and overriding. For this I have the following 'base' class
#pragma once
#include <iostream>
#include <string>
using namespace std::string_view_literals;
struct vtable;
class IdentityDocument {
public:
IdentityDocument()
: vtable_ptr_(&IdentityDocument::VTABLE),
unique_id_(++unique_id_count_)
{
std::cout << "IdentityDocument::Ctor() : "sv << unique_id_ << std::endl;
}
~IdentityDocument() {
--unique_id_count_;
std::cout << "IdentityDocument::Dtor() : "sv << unique_id_ << std::endl;
}
IdentityDocument(const IdentityDocument& other)
: vtable_ptr_(other.vtable_ptr_),
unique_id_(++unique_id_count_)
{
std::cout << "IdentityDocument::CCtor() : "sv << unique_id_ << std::endl;
}
IdentityDocument& operator=(const IdentityDocument&) = delete;
void PrintID() const {
std::cout << "IdentityDocument::PrintID() : "sv << unique_id_ << std::endl;
}
static void PrintUniqueIDCount() {
std::cout << "unique_id_count_ : "sv << unique_id_count_ << std::endl;
}
int GetID() const {
return unique_id_;
}
private:
vtable* vtable_ptr_ = nullptr;
static int unique_id_count_;
static vtable VTABLE;
int unique_id_;
};
struct vtable
{
void (IdentityDocument::* const PrintID)() const;
vtable (
void (IdentityDocument::* const PrintID)() const
) : PrintID(PrintID) {}
};
int IdentityDocument::unique_id_count_ = 0;
vtable IdentityDocument::VTABLE = {&IdentityDocument::PrintID};
And here is another class that must override PrintId method
#pragma once
#include "identity_document.h"
#include <iostream>
#include <string>
#include <ctime>
using namespace std::string_view_literals;
class Passport {
public:
Passport()
: expiration_date_(GetExpirationDate())
{
IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
vtable_ptr = &Passport::VTABLE;
std::cout << "Passport::Ctor()"sv << std::endl;
}
Passport(const Passport& other)
: identity_(other.identity_)
, expiration_date_(other.expiration_date_)
{
IdentityDocument* base_ptr = reinterpret_cast<IdentityDocument*>(this);
vtable* vtable_ptr = reinterpret_cast<vtable*>(base_ptr);
vtable_ptr = &Passport::VTABLE;
std::cout << "Passport::CCtor()"sv << std::endl;
}
~Passport() {
std::cout << "Passport::Dtor()"sv << std::endl;
}
void PrintID() const {
std::cout << "Passport::PrintID() : "sv << identity_.GetID();
std::cout << " expiration date : "sv << expiration_date_.tm_mday << "/"sv << expiration_date_.tm_mon << "/"sv
<< expiration_date_.tm_year + 1900 << std::endl;
}
void PrintVisa(const std::string& country) const {
std::cout << "Passport::PrintVisa("sv << country << ") : "sv << identity_.GetID() << std::endl;
}
private:
IdentityDocument identity_;
const struct tm expiration_date_;
static vtable VTABLE;
tm GetExpirationDate() {
time_t t = time(nullptr);
tm exp_date = *localtime(&t);
exp_date.tm_year += 10;
mktime(&exp_date);
return exp_date;
}
};
vtable Passport::VTABLE = {reinterpret_cast<void (IdentityDocument::*)() const>(&Passport::PrintID)};
And a short demo :
int main() {
array<IdentityDocument*, 1> docs = { (IdentityDocument*)(new Passport()) };
for (const auto* doc : docs) {
doc->PrintID();
}
}
Unfortunately, I see that the 'derived' method was not called. Am I using a wrong approach to implement a vtable concept?
Am I using a wrong approach to implement a vtable concept?
Yes. You have not written any code that reads your vtable, and the C++ compiler will not generate any code to read your vtable either.
When you declare a member function virtual, your compiler needs to call that function in a special way. Any call to that function should be looked up in a vtable.
When a member function is not virtual, your compiler knows that it doesn't need to look up the location of the function. It knows which function to call. No lookup needed.
In your code, you have created a vtable, but this line, calling a non-virtual function:
doc->PrintID();
Does not need a vtable, and does not check for one.
doc is an IdentityDocument*, so doc->PrintID() calls IdentityDocument::PrintID(). No lookup required, no lookup happens.
Finally I simplified my solution and got what I wanted :
#include <iostream>
class A;
struct VTable
{
void (*say_hello)(A*);
};
class A
{
public:
A()
{
vtable.say_hello = A::sayHello;
}
void sayHello()
{
vtable.say_hello(this);
}
static void sayHello(A* a)
{
std::cout << "A::sayHello" << std::endl;
}
VTable vtable;
};
class B
{
public:
B()
{
a.vtable.say_hello = B::sayHello;
}
void sayHello()
{
a.vtable.say_hello((A*)this);
}
static void sayHello(A* a)
{
std::cout << "B::sayHello\n" << std::endl;
}
private:
A a;
};
int main()
{
A* a = (A*)(new B);
a->sayHello();
delete a;
}

How to return the member of template derived class from base?

Is it possible to return a template member of a derived class by the base?
Please find the following classes:
Data.h:
#include <string>
class IData{
public:
virtual ~IData(){};
virtual const std::string& getName() const = 0;
};
template <typename T>
class DataImpl: public IData
{
public:
DataImpl(const std::string& name, T* ptrToData)
:_name(name)
,_ptrToData(ptrToData)
{};
~DataImpl(){};
const std::string& getName() const
{
return _name;
}
const T* getDataPtr() const
{
return _ptrToData;
}
private:
std::string _name;
T* _ptrToData; // <-- how to return this pointer ?
};
Component.h:
#include <vector>
#include <string>
#include "Data.h"
class Component
{
public:
Component(const std::string& name)
:_name(name)
{};
~Component(){};
const std::string& getName() const
{
return _name;
};
std::vector<IData*>& getDataList()
{
return _dataList;
};
void addData(IData* ptr)
{
_dataList.push_back(ptr);
};
private:
std::string _name;
std::vector<IData*> _dataList;
};
main.cpp:
#include <iostream>
#include <vector>
#include <string>
#include "Component.h"
#include "Data.h"
int main()
{
// primitive types
int x = 5;
float y = 5.7;
bool b = false;
// complex structures
struct complex{
int a;
std::string c;
};
complex cx;
cx.a = 5;
cx.c = "anything";
DataImpl<int> d1("x", &x);
DataImpl<float> d2("y", &y);
DataImpl<bool> d3("b", &b);
DataImpl<complex> d4("complex", &cx);
Component cmp("cmpName");
cmp.addData(&d1);
cmp.addData(&d2);
cmp.addData(&d3);
cmp.addData(&d4);
std::vector<IData*>::iterator it = cmp.getDataList().begin();
for (;it != cmp.getDataList().end(); ++it)
{
IData* ptr = *it;
std::cout << ptr->getName() << std::endl;
}
return 0;
}
Inside the loop in the main.cpp, I was accessing every DataImpl member. But I want to return/get the member variable T* _ptrToData through the base class IData but so far I did not find any way.
I have a compiler restriction to c++98
Thanks in advance.
You can try to use dynamic_cast to perform a type-safe downcast of the IData* pointer back to the pointer of the derived class (e.g. DataImpl<int>* ) . However, this may require the Run-time type information (RTTI) of the compiler enabled.
Here's an example:
for (;it != cmp.getDataList().end(); ++it)
{
IData* ptr = *it;
std::cout << ptr->getName() << std::endl;
DataImpl<int>* pInt = dynamic_cast<DataImpl<int>*>(ptr);
if (pInt) {
std::cout << "*pInt->getDataPtr(): " << *pInt->getDataPtr() << std::endl;
std::cout << "pInt->getDataPtr(): " << pInt->getDataPtr() << std::endl;
}
DataImpl<float>* pfloat = dynamic_cast<DataImpl<float>*>(ptr);
if (pfloat) {
std::cout << "*pfloat->getDataPtr(): " << *pfloat->getDataPtr() << std::endl;
std::cout << "pfloat->getDataPtr(): " << pfloat->getDataPtr() << std::endl;
}
DataImpl<bool>* pbool = dynamic_cast<DataImpl<bool>*>(ptr);
if (pbool) {
std::cout << "*pbool->getDataPtr(): " << *pbool->getDataPtr() << std::endl;
std::cout << "pbool->getDataPtr(): " << pbool->getDataPtr() << std::endl;
}
}

Cannot instantiate abstract class?

I got this:
class Core
{
protected:
static unsigned int id_seed;
unsigned int id;
std::string status;
public:
friend class CPU;
Core();
~Core();
virtual void procesare(std::string aplicatie) = 0;
};
class CoreScreen: public Core
{
public:
CoreScreen();
~CoreScreen();
void procesare(std::string aplicatie);
};
and corescreen.cpp:
#include "CoreScreen.h"
CoreScreen::CoreScreen()
{
}
CoreScreen::~CoreScreen()
{
}
void CoreScreen::procesare(std::string aplicatie)
{
std::string buffer;
std::ifstream file_in(aplicatie);
if (file_in.is_open()) {
std::cout << "Aplicatia " << aplicatie << " ruleaza: " << std::endl;
while (getline(file_in, buffer)) {
std::cout << buffer;
}
file_in.close();
}
else {
throw new CExceptie(APP_FAIL, " Aplicatia nu a putut rula!");
}
}
When I use in main:
CoreScreen CS1, CS2, CS3, CS4;
I get this error: 'Core' cannot instantiate abstract class.
What's the problem? I thought I have my virtual function declared in CoreScreen correctly.
As I presume you know, "Core" is an abstract class, by virtue of the fact it has a pure virtual function: virtual void procesare(std::string aplicatie) = 0;.
I presume you also know that you can't instantiate an abstract class: hence your error.
The question is:
Why does the compiler think you're trying to instantiate an instance of "Core"?
Are you?
It looks like you're trying to instantiate four CoreScreen objects: CoreScreen CS1, CS2, CS3, CS4;. If so, that should be perfectly OK.
You're correct: procesare() is virtual ("pure virtual", as it happens). You've indeed overridden it correctly in CoreScreen.cpp: it DOESN'T look like that's the problem.
Q: Did you ever implement Core::Core() and Core::~Core() anywhere? If not, how did you even compile?
Q: Are you SURE you're not trying to create an instance of "Core" anywhere (even "accidentally")?
For whatever it's worth, the following MCVE compiles and runs fine (Ubuntu 18, GCC 7.3.0):
TestCore.h:
/*
* TestCore.h
*/
#ifndef TESTCORE_H_
#define TESTCORE_H_
#include <string>
class Core
{
protected:
static unsigned int id_seed;
unsigned int id;
std::string status;
public:
friend class CPU;
Core();
~Core();
virtual void procesare(std::string aplicatie) = 0;
};
class CoreScreen: public Core
{
public:
CoreScreen();
~CoreScreen();
void procesare(std::string aplicatie);
};
#endif /* TESTCORE_H_ */
TestCore.cpp:
/*
* TestCore.cpp
*/
#include <iostream>
#include <fstream>
#include "TestCore.h"
Core::Core()
{
std::cout << "Core::Core()..." << std::endl;
}
Core::~Core()
{
std::cout << "Core::~Core()..." << std::endl;
}
CoreScreen::CoreScreen()
{
std::cout << "CoreScreen::CoreScreen()..." << std::endl;
}
CoreScreen::~CoreScreen()
{
std::cout << "CoreScreen::~CoreScreen()..." << std::endl;
}
void CoreScreen::procesare(std::string aplicatie)
{
std::cout << "CoreScreen::procesare(" << aplicatie << ")" << std::endl;;
}
int main () {
std::cout << ">>main()..." << std::endl;
CoreScreen CS1, CS2, CS3, CS4;
CS1.procesare("Testing CS1");
std::cout << "<<main()." << std::endl;
return 0;
}
SAMPLE OUTPUT:
>>main()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
Core::Core()...
CoreScreen::CoreScreen()...
CoreScreen::procesare(Testing CS1)
<<main().
You'll note that I implemented Core::Core() and Core::~Core(). If you don't need them - then don't even put them in your .h class definition.
'Hope that helps

Retrieving values of an object from an array?

Pardon the example but in this case:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
};
class B {
private:
A theArray[1];
public:
void set(const A value) {theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
Is it possible for me to retrieve the contents of the "man" object in main when I call manPlace.get()? My intention is to print both the name (Bob) and the age (25) when I call manPlace.get(). I want to store an object within an array within another class and I can retrieve the contents of said array within the main.
You need to define a ostream::operator<< on your A class to accomplish that - otherwise the format how age and name should be generated as text-output is undefined (and they are private members of your A class).
Take a look at the reference for ostream::operator<<. For your A class, such a operator could be defined like this:
std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
Which would output something like:
Name: XX
Age: YY
So your complete code would be:
#include <iostream>
#include <string>
using namespace std;
class A {
private:
string theName;
int theAge;
public:
A() : theName(""), theAge(0) { }
A(string name, int age) : theName(name), theAge(age) { }
friend std::ostream& operator<< (std::ostream &out, A &a) {
out << "Name: " << a.theName << std::endl;
out << "Age: " << a.theAge << std::endl;
return out;
}
};
class B {
private:
A theArray[1];
public:
void set(const A value) { theArray[0] = value; }
A get() const { return theArray[0]; }
};
int main()
{
A man("Bob", 25);
B manPlace;
manPlace.set(man);
cout << manPlace.get();
return 0;
}
which will output:
Name: Bob
Age: 25

How can I use the boost visitor concept with a class containing state variables?

I'm attempting to use boost::static_visitor to implement actions on a boost::variant type that affect the state of some variable. My approach was to contain all of the state variables in my command visitor class, but it seems this is not possible.
Here is my code example:
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t) const
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator(TypeB & t) const
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
I hope this snippet gets across the gist of what I'm trying to accomplish. It won't compile, however, giving the [paraphrased] error:
error: no operator "<<" matches these operands
operand types are: const std::stringstream << const char [N]
m_outStream << "TYPE A ACTION: " << t.varB << std::endl;
^
I'm assuming this error is due to the const modifier that must be placed on the end of the operator() function prototype which makes the compiler believe that member variables cannot be modified by the function.
My question is thus:
What is the proper way to accomplish the visitor pattern (using boost::variant) with variables that must maintain state between visits?
There were a couple of typos, but I made a few mods and it works now. Essentially your static_visitor class is mutating itself on each visit, so the operator() methods can't be const.
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#include <iostream>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t)
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator()(TypeB & t)
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream m_outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
running on http://www.compileonline.com/compile_cpp11_online.php gives:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
Result:
TYPEA ACTION: 2
String2 ACTION String1
I'd personally favour making the functor const. Instead, I like to bind the functor arguments to references:
static std::string emitWork(std::vector<MyVariantType> const listOfVariants) {
int sum = 0, charCount = 0;
std::stringstream os;
BOOST_FOREACH(MyVariantType const& v, listOfVariants) {
boost::apply_visitor(
boost::bind(MyCommandVisitor(), _1, boost::ref(os), boost::ref(sum), boost::ref(charCount)),
v);
}
return os.str();
}
Note that
emitWork can now be static, reentrant etc.
the operator() can now be const
The rest of the visitor would look like this:
struct MyCommandVisitor : boost::static_visitor<> {
void operator()(TypeA const& t, std::stringstream& os, int& sum, int& /*charCount*/) const {
sum += t.varA;
os << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator()(TypeB const& t, std::stringstream& os, int& /*sum*/, int& charCount) const {
charCount += t.varA.size();
os << t.varB << " ACTION " << t.varA << std::endl;
}
};
See it Live On Coliru