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
Related
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;
}
I'm trying to understand virtual classes in C++. In Wikipedia, I found this example:
#include <iostream>
class Machine {
public:
void run() { }
class Parts {
public:
virtual int get_wheels() = 0;
virtual std::string get_fuel_type() = 0;
};
};
// The inner class "Parts" of the class "Machine" may return the number of wheels the machine has.
class Car: Machine {
public:
void run() {
std::cout << "The car is running." << std::endl;
}
class Parts: Machine::Parts {
public:
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
};
I can get the number of wheels of a car with:
Car::Parts c_p;
c_p.get_wheels();
Is there any other (simple) way? Is there any way instantiating only Car car ?
Update:
I understand the concerns, but I find it useful as a nested interface (with minimal changes):
#include <iostream>
#include <memory>
class Machine {
public:
virtual void run() = 0;
class Parts {
public:
virtual int get_wheels() = 0;
virtual std::string get_fuel_type() = 0;
};
};
class Car: public Machine {
public:
void run() {
std::cout << "The car is running." << std::endl;
}
class Parts: public Machine::Parts {
public:
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
};
int main () {
std::shared_ptr<Machine> X = std::make_shared<Car>();
(*X).run();
std::shared_ptr<Machine::Parts> Y = std::make_shared<Car::Parts>();
(*Y).get_wheels();
return 0;
}
I don't find any other code with this functionality. The only thing I miss is the possibility to access get_wheels directly from X. For instance, let's consider that I have a Machine in my program. The kind of machine I have will be specified dynamically. I want to know the number of wheels of this machine, but the method get_wheels must be inside a nested class Parts. The closer to solve this problem that I've got is with the code above, which gives me Machine and Machine::Parts as interfaces.
A simple solution would be to have a member part of you car:
struct Car : Machine {
struct Parts : Machine::Parts {
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
} parts; // <---
// or declare it as a separated member:
// Parts parts;
};
That way, you can call member functions like this:
Car car;
std::cout << car.parts.get_weels();
No. As it stands, a Car instance does not have any Car::Parts instances, nor any method that returns one.
The text around the example seems to be assuming that there is an instance of Machine::Parts associated with Machine somehow, which magically becomes a Car::Parts in Car. This may be the case in some other language, but it is not the case in C++.
A much more idomatic design would be to have a traits class template that Machine subclasses specialise.
template <typename Machine>
struct MachineParts;
template <>
struct MachineParts<Car> {
static int get_wheels() {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
static std::string get_fuel_type() {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
template <>
struct MachineParts<Bicycle> {
static int get_wheels() {
std::cout << "A bike has 2 wheels." << std::endl;
return 2;
}
static std::string get_fuel_type() {
std::cout << "A bike uses muscles for fuel." << std::endl;
return "muscles";
}
};
I included the logger from boost. I'm pretty pleased how it works. Just for simplicity and the reason I don't want to use makros to often in my code, I wrap it in a class.
I now wonder if I could use the streaming operator << to write on a member function.
code
class LogWrapper{
...
//debug function
//info function
...
}
void main() {
LogWrapper log;
log.debug() << "some debug msg"; // does this exist?
log.info() << "some info msg";
}
output
[some_timestamp][debug] some debug msg
[some_timestamp][info] some info msg
Is this possible in a good practice, or is it entirely bad style?
It can be done easily like this:
#include <iostream>
class A {
public:
std::ostream &debug() const {
std::cerr << "[timestamp]" << "[DEBUG]";
return std::cerr;
}
};
int main()
{
A a;
a.debug() << "Test";
}
But the important question here is: Should we implement it in this way? In my opinion, NO!
Because you are thinking that the User of the class will print the logs like this:
int main()
{
A a;
a.debug() << "Test" << std::endl;
a.debug() << "Test2" << std::endl;
}
Output:
[timestamp][DEBUG]Test
[timestamp][DEBUG]Test2
But what if User chooses this way:
int main()
{
A a;
auto &out = a.debug();
out << "Test" << std::endl;
out << "Test2" << std::endl;
}
Output:
[timestamp][DEBUG]Test
Test2
I would highly recommend not to return stream object. You should use member functions for this purpose.
#include <iostream>
class A {
public:
static void debug(const std::string &log) {
std::cerr << "[timestamp]" << "[DEBUG]" << log << std::endl;
}
};
int main()
{
A::debug("Test 1");
A::debug("Test 2");
}
Output:
[timestamp][DEBUG]Test 1
[timestamp][DEBUG]Test 2
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.
I stumbled across this piece of code when I researched for a good example for Observer Design pattern. In main, it gets error, taking address of temporary[-fpermissive] which I dont dont understand what it is frankly. Sending a class refference to an function? Is this real life?
#include <vector>
#include <iostream>
using namespace std;
class AlarmListener
{
public:
virtual void alarm() = 0;
};
class SensorSystem
{
vector < AlarmListener * > listeners;
public:
void attach(AlarmListener *al)
{
listeners.push_back(al);
}
void soundTheAlarm()
{
for (int i = 0; i < listeners.size(); i++)
listeners[i]->alarm();
}
};
class Lighting: public AlarmListener
{
public:
/*virtual*/void alarm()
{
cout << "lights up" << '\n';
}
};
class Gates: public AlarmListener
{
public:
/*virtual*/void alarm()
{
cout << "gates close" << '\n';
}
};
class CheckList
{
virtual void localize()
{
cout << " establish a perimeter" << '\n';
}
virtual void isolate()
{
cout << " isolate the grid" << '\n';
}
virtual void identify()
{
cout << " identify the source" << '\n';
}
public:
void byTheNumbers()
{
// Template Method design pattern
localize();
isolate();
identify();
}
};
// class inheri. // type inheritance
class Surveillance: public CheckList, public AlarmListener
{
/*virtual*/void isolate()
{
cout << " train the cameras" << '\n';
}
public:
/*virtual*/void alarm()
{
cout << "Surveillance - by the numbers:" << '\n';
byTheNumbers();
}
};
int main()
{
SensorSystem ss;
ss.attach(&Gates());
ss.attach(&Lighting());
ss.attach(&Surveillance());
ss.soundTheAlarm();
}
This is ill-formed:
ss.attach(&Gates());
^^^
Gates() is an rvalue (specifically, a prvalue). You cannot take the address of an rvalue. It's not an object that has identity, so it doesn't really have an address that you can take. The language is preventing you from doing something that doesn't make sense to do. If you did store a pointer to this temporary, you'd just end up with a dangling pointer since at the end of this line the temporary Gates would be destroyed.
Since SensorSystem doesn't own its AlarmListeners, you'll have to create them up front:
Gates gates;
Lighting lighting;
Surveillance surveillance;
SensorSystem ss;
ss.attach(&gates);
ss.attach(&lighting);
ss.attach(&surveillance);