I'm working on compiling the code for Acellerated c++ chapter 15. I more or less copied the code straight out of the book, except in some places they defined things like constructors in the class body in the header file, and I separated them out to avoid link errors.
Below is the code; I attempted to compile it in Visual Studio 2010, but unfortunately it fails. It tells me it cannot create instances of the "String_Pic" and the other derived classes (Frame_Pic, HCat_Pic, and VCat_Pic) because it says they are still abstract classes. It says the culprit is the "display" function, which it says is undefined. However, I clearly define it for each derived class, as you can see below.
What's going on here?
Header:
#ifndef _GUARD_PIC_BASE_H
#define _GUARD_PIC_BASE_H
#include "Ptr.h"
#include <iostream>
#include <string>
#include <vector>
class Picture;
class Pic_base {
friend std::ostream& operator<<(std::ostream&, const Picture&);
friend class Frame_Pic;
friend class HCat_Pic;
friend class VCat_Pic;
friend class String_Pic;
typedef std::vector<std::string>::size_type ht_sz;
typedef std::string::size_type wd_sz;
virtual wd_sz width() const = 0;
virtual ht_sz height() const = 0;
virtual void display(std::ostream, ht_sz, bool) const = 0;
public:
virtual ~Pic_base(){ }
protected:
static void pad(std::ostream&, wd_sz, wd_sz);
};
// public interface class and operations
class Picture {
friend std::ostream& operator<<(std::ostream&, const Picture&);
friend Picture frame(const Picture&);
friend Picture hcat(const Picture&, const Picture&);
friend Picture vcat(const Picture&, const Picture&);
public:
Picture(const std::vector<std::string>& =
std::vector<std::string>());
private:
Picture(Pic_base* ptr); //here's one difference
Ptr<Pic_base> p;
};
Picture frame(const Picture&);
Picture hcat(const Picture&, const Picture&);
Picture vcat(const Picture&, const Picture&);
std::ostream& operator<<(std::ostream&, const Picture&);
class String_Pic: public Pic_base {
friend class Picture;
std::vector<std::string> data;
String_Pic(const std::vector<std::string>&);
wd_sz width() const;
ht_sz height() const;
void display(std::ostream&, ht_sz, bool) const;
};
class VCat_Pic: public Pic_base {
friend Picture vcat(const Picture&, const Picture&);
Ptr<Pic_base> top, bottom;
VCat_Pic(const Ptr<Pic_base>&, const Ptr<Pic_base>&);
wd_sz width() const;
ht_sz height() const;
void display(std::ostream&, ht_sz, bool) const;
};
class HCat_Pic: public Pic_base {
friend Picture hcat(const Picture&, const Picture&);
Ptr<Pic_base> left, right;
HCat_Pic(const Ptr<Pic_base>&, const Ptr<Pic_base>&);
wd_sz width() const;
ht_sz height() const;
void display(std::ostream&, ht_sz, bool) const;
};
class Frame_Pic: public Pic_base {
friend Picture frame(const Picture&);
Ptr<Pic_base> p;
Frame_Pic(const Ptr<Pic_base>& pic);
wd_sz width() const;
ht_sz height() const;
void display(std::ostream&, ht_sz, bool) const;
};
#endif
.cpp/implementation file:
#include "Ptr.h"
#include "Pic_Base.h"
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
//Picture-Specific Functions:
Picture::Picture(Pic_base* ptr):p(ptr) {}
Picture::Picture(const vector<string>& v): p(new String_Pic(v)) { }
//Frame-Specific Functions:
Frame_Pic::Frame_Pic(const Ptr<Pic_base>& pic): p(pic) {}
Pic_base::wd_sz Frame_Pic::width() const { return p->width() + 4; }
Pic_base::ht_sz Frame_Pic::height() const { return p->height() + 4; }
void Frame_Pic::display(ostream& os, ht_sz row, bool do_pad) const{
if (row >= height()) {
// out of range
if (do_pad)
pad(os, 0, width());
} else {
if (row == 0 || row == height() - 1) {
// top or bottom row
os << string(width(), '*');
} else if (row == 1 || row == height() - 2) {
// second from fop or bottom row
os << "*";
pad(os, 1, width() - 1);
os << "*";
} else {
// interior row
os << "* ";
p->display(os, row - 2, true);
os << " *";
}
}
}
Picture frame(const Picture& pic){
return new Frame_Pic(pic.p);
}
//HCat-Specific Functions:
HCat_Pic::HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>& r): left(l), right(r) { }
HCat_Pic::HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>&r):
left(l), right(r) { }
Pic_base::wd_sz width() const { return left->width() + right->width(); }
Pic_base::ht_sz height() const { return max(left->height(), right->heigth()); }
void HCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const{
left->display(os, row, do_pad || row < right->height());
right->display(os, row, do_pad);
}
Picture hcat(const Picture& l, const Picture& r){
return new HCat_Pic(l.p, r.p);
}
//VCat-Specific Functions:
VCat_Pic::VCat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b): top(t), bottom(b) { }
Picture vcat(const Picture& t, const Picture& b){
return new VCat_Pic(t.p, b.p);
}
Pic_base::wd_sz VCat_Pic::width() const {
return max(top->width(), bottom->width());
}
Pic_base::ht_sz VCat_Pic::height() const{
return top->height() + bottom->height();
}
void VCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const{
wd_sz w = 0;
if (row < top->height()) {
// we are in the top subpicture
top->display(os, row, do_pad);
w = top->width();
} else if (row < height()) {
// we are in the bottom subpicture
bottom->display(os, row - top->height(), do_pad);
w = bottom->width();
}
if (do_pad)
pad(os, w, width());
}
//String_Pic-Specific Functions:
String_Pic::String_Pic(const std::vector<std::string>& v): data(v) { }
Pic_base::ht_sz String_Pic::height() const { return data.size(); }
Pic_base::wd_sz String_Pic::width() const{
Pic_base::wd_sz n = 0;
for (Pic_base::ht_sz i = 0; i != data.size(); ++i)
n = max(n, data[i].size());
return n;
}
void String_Pic::display(ostream& os, ht_sz row, bool do_pad) const{
wd_sz start = 0;
// write the row if we're still in range
if (row < height()) {
os << data[row];
start = data[row].size();
}
// pad the output if necessary
if (do_pad)
pad(os, start, width());
}
//Pic_base-Specific functions:
void Pic_base::pad(std::ostream& os, wd_sz beg, wd_sz end) {
while (beg != end) {
os << " ";
++beg;
}
}
//Non-Specific Functions:
ostream& operator<<(ostream& os, const Picture& picture){
const Pic_base::ht_sz ht = picture.p->height();
for (Pic_base::ht_sz i = 0; i != ht; ++i) {
picture.p->display(os, i, false);
os << endl;
}
return os;
}
You declare the pure virtual function as taking a ofstream object by value, while all your subclasses define it as taking a reference to one.
virtual void display(std::ostream, ht_sz, bool) const = 0;
vs
void display(std::ostream&, ht_sz, bool) const;
^
Pi_base declares display with this signature:
virtual void display(std::ostream, ht_sz, bool) const = 0;
But your derived classes declare it with this signature:
void display(std::ostream&, ht_sz, bool) const;
Compare them closely and you'll see that your base class takes a std::ostream while your derived classes take a std::ostream&.
Related
I'm using visual studio.
I have 3 class.
It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()
I know it's something up to the pointer in class Rectangle but can't firgure out.
`int main(){
Array<Rectangle>A;
Rectangle a;
cout << a; //It's oke
A.PushBack(a); // problem here
cout<<a;
}`
class Point
{
private:
float _x;
float _y;
public:
float GetX() { return _x; }
float GetY() { return _y; }
public:
Point();
Point(float, float);
Point(const Point&);
~Point() {};
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Point*);
friend ostream& operator<<(ostream&, const Point&);
};
Point::Point() {
_x = 1;
_y = 1;
}
Point::Point(float x, float y) {
_x = x;
_y = y;
}
Point::Point(const Point& a) {
_x = a._x;
_y = a._y;
}
string Point::ToString() const{
stringstream out;
out << "( " << _x << "," << _y << " )";
return out.str();
}
istream& operator>>(istream& in, Point* a) {
cout << "Nhap x: ";
in >> a->_x;
cout << "Nhap y: ";
in >> a->_y;
return in;
}
ostream& operator<<(ostream& out, const Point& a)
{
out << a.ToString();
return out;
}
```
class Rectangle
{
private:
Point* _topleft;
Point* _botright;
public:
void Set_topleft(Point tl) { _topleft = &tl; }
Point Get_topleft() { return *_topleft; }
void Set_botright(Point br) { _botright = &br; }
Point Get_botright() { return *_botright; }
public:
Rectangle();
Rectangle(Point*, Point*);
~Rectangle();
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Rectangle&);
friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
_topleft = new Point(0, 2);
_botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
_topleft = new Point(*a);
_botright = new Point(*b);
}
Rectangle::~Rectangle()
{
delete _topleft;
delete _botright;
}
string Rectangle::ToString() const
{
stringstream out;
out << "A" << *_topleft << "+" << "D" << *_botright;
return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
std::cout << "A( x,y ): ";
in >> a._topleft;
std::cout << "D( x,y ): ";
in >> a._botright;
return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
out << a.ToString();
return out;
}
```
template<class T>
class Array
{
private:
T* _a;
int _len;
public:
Array();
~Array();
public:
int length() { return _len; }
void PushBack(T);
T GetAt(int);
};
template<class T>
Array<T>::Array() {
_a = new T[128];
_len = 0;
}
template<class T>
Array<T>::~Array() {
delete[] _a;
_len = 0;
}
template<class T>
void Array<T>::PushBack(T value) {
if (_len >= 128)
{
std::cout << "Array is over size, which is 128\n";
return;
}
_a[_len] = value;
_len++;
}
template<class T>
T Array<T>::GetAt(int pos) {
return _a[pos];
}
```
The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory.
To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.
Rectangle(const Rectangle &other)
{
if(other._topleft)
_topleft= new Point(*other._topleft);
else
_topleft = nullptr;
if(other._botright)
_botright= new Point(*other._botright);
else
_topleft = nullptr;
}
The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value).
Also, try Rectangle(Rectangle&& o) = delete;
I am working on my school project that has a base class and a derived class with some other classes.
Product.h
#ifndef AMA_PRODUCT_H
#define AMA_PRODUCT_H
#include <iostream>
#include <fstream>
namespace AMA
{
const int max_sku_length = 7;
const int max_unit_length = 10;
const int max_name_length = 75;
const double TRate = 0.13;
class Product
{
private:
char m_type;
char m_sku[max_sku_length +1];
char m_unit[max_unit_length + 1];
char* m_name;
int m_Cquantity;
int m_Nquantity;
double m_price;
bool m_status;
protected:
void sku(const char* setSku) { strncpy(m_sku, setSku, max_sku_length); }
const char* name() const { return m_name; }
bool taxed() const { return m_status; }
const char* sku() const { return m_sku;}
void name(const char*);
const char* unit() const;
double price() const;
void message(const char*);
bool isClear() const;
public:
double cost() const;
bool operator==(const char* src) { return strcmp(m_sku, src) == 0; }
bool isEmpty() const { return ((m_sku[0] == '\0') && (m_name == nullptr) && (m_price == 0) && (m_Cquantity == 0)); }
int qtyNeeded() const { return m_Nquantity; }
int quantity() const { return m_Cquantity; }
int operator+=(int src) { return m_Cquantity += src; }
Product();
Product(const char* sku, const char* name, const char* unit, int qty = 0,
bool taxed = true, double price = 0.0, int qtyNeeded = 0);
Product(const Product&);
Product& operator=(const Product&);
~Product();
virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const = 0;
virtual std::fstream& load(std::fstream& file) = 0;
virtual std::ostream& write(std::ostream& os, bool linear)const = 0;
virtual std::istream& read(std::istream& is) = 0;
double total_cost() const;
void quantity(int);
bool operator>(const char*) const;
bool operator>(const Product&) const;
};
std::ostream& operator<<(std::ostream&, const Product&);
std::istream& operator>>(std::istream&, Product&);
double operator+=(double&, const Product&);
}
#endif
MyProduct.h
#ifndef AMA_MY_PRODUCT_H
#define AMA_MY_PRODUCT_H
#include <fstream>
#include "Product.h"
#include "ErrorState.h"
namespace AMA {
class MyProduct : public Product {
public:
MyProduct();
MyProduct(const char* sku, const char* name, const char* unit, int qty = 0,
bool isTaxed = true, double price = 0.0, int qtyNeeded = 0);
const char* sku() const;
const char* name() const;
const char* unit() const;
bool taxed() const;
double price() const;
double cost() const;
};
class Test {
MyProduct product; // Error
const char* filename;
public:
Test(const char* file);
Test(const char* file, const char* theSku, const char* theName);
std::fstream& store(std::fstream& file, bool addNewLine = true) const;
std::fstream& load(std::fstream& file);
std::ostream& write(std::ostream& os, bool linear) const;
std::istream& read(std::istream& is);
int operator+=(int value);
bool operator==(const char* sku) const;
friend std::ostream& operator<<(std::ostream& os, const Test& test);
friend double operator+=(double& d, const Test& test);
friend std::istream& operator>>(std::istream& is, Test& test);
};
}
#endif
MyProduct.cpp
#include <iomanip>
#include <fstream>
#include <cstring>
#include "MyProduct.h"
#ifdef TAB
#undef TAB
#endif
#define TAB '\t'
using namespace std;
namespace AMA {
MyProduct::MyProduct() : Product("", "", "") {}
MyProduct::MyProduct(const char* sku, const char* name, const char* unit, int qty,
bool isTaxed, double price, int qtyNeeded) :
Product(sku, name, unit, qty, isTaxed, price, qtyNeeded) {}
const char* MyProduct::sku() const { return Product::sku(); }
const char* MyProduct::name() const { return Product::name(); }
const char* MyProduct::unit() const { return Product::unit(); }
bool MyProduct::taxed() const { return Product::taxed(); }
double MyProduct::price() const { return Product::price(); }
double MyProduct::cost() const { return Product::cost(); }
Test::Test(const char* file) : filename(file) { }
Test::Test(const char* file, const char* theSku, const char* theName) :
product(theSku, theName, ""), filename(file) { }
std::fstream& Test::store(std::fstream& file, bool addNewLine) const {
if (!product.isEmpty()) {
file.open(filename, ios::out | ios::app);
file << product.sku() << TAB << product.name() << TAB << product.unit() << TAB <<
(product.taxed() ? 1 : 0) << TAB << product.price() << TAB << product.quantity() << TAB <<
product.qtyNeeded() << endl;
file.clear();
file.close();
}
return file;
}
std::fstream& Test::load(std::fstream& file) {
char sku_[max_sku_length + 1];
char name[max_name_length + 1];
char unit[max_unit_length + 1];
int quantity, qtyNeeded;
double price_;
char taxed_;
file.open(filename, ios::in);
file >> sku_;
file >> name;
file >> unit;
file >> taxed_;
file >> price_;
file >> quantity;
file >> qtyNeeded;
file.clear();
file.close();
product = MyProduct(sku_, name, unit, quantity, taxed_ != 0, price_, qtyNeeded); //ERROR
return file;
}
std::ostream& Test::write(std::ostream& os, bool linear) const {
return product.isEmpty() ? os : (os << product.sku() << ": " << product.name() << ", quantity: "
<< product.quantity() << ", quantity needed:" << product.qtyNeeded()
<< ", Cost: " << fixed << setprecision(2) << product.cost());
}
std::istream& Test::read(std::istream& is) {
char sku_[max_sku_length + 1];
char name[max_name_length + 1];
char unit[max_unit_length + 1];
int quantity, qtyNeeded;
double price_;
char taxed_;
cout << " Sku: ";
is >> sku_;
cout << " Name (no spaces): ";
is >> name;
cout << " Unit: ";
is >> unit;
cout << " Taxed? (y/n): ";
is >> taxed_;
cout << " Price: ";
is >> price_;
cout << " Quantity On hand: ";
is >> quantity;
cout << " Quantity Needed: ";
is >> qtyNeeded;
product = MyProduct(sku_, name, unit, quantity, taxed_ != 0, price_, qtyNeeded); //ERROR
return is;
}
int Test::operator+=(int value) {
product.quantity(product += value);
return product.quantity();
}
bool Test::operator==(const char* sku) const {
return !std::strcmp(product.sku(), sku);
}
std::ostream& operator<<(std::ostream& os, const Test& test) {
return test.product.write(os, true);
}
double operator+=(double& d, const Test& test) {
return d += test.product.total_cost();
}
std::istream& operator>>(std::istream& is, Test& test) {
return test.product.read(is);
}
}
I am getting errors that I don't really know how to fix
object of abstract class type "AMA::MyProduct" is not allowed
'AMA::MyProduct': cannot instantiate abstract class
a cast to abstract class "AMA::MyProduct" is not allowed
Can someone help me out please?
The errors are self explanatory.
AMA::MyProduct is an abstract class, and such it cannot be instantiated directly.
A class is abstract when it has at least 1 abstract method (virtual and = 0 keywords on it). An abstract method MUST be overridden in a derived class, and you MUST instantiate that derived class, not the abstract class.
AMA::MyProduct is abstract because it does not override the 4 abstract methods it inherits from AMA::Product:
virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const = 0;
virtual std::fstream& load(std::fstream& file) = 0;
virtual std::ostream& write(std::ostream& os, bool linear)const = 0;
virtual std::istream& read(std::istream& is) = 0;
You implemented them in AMA::Test instead of in AMA::MyProduct.
I was trying to follow the SFML Blueprint book. I managed to remove all the errors but one error remains in the code.
I have tried to find about the debug-assertion-failed.
I think this issue is arising due to the lists one of them is getting emptied.
My code for the world.cpp
#include "World.h"
#include "Entity.h"
World::World(int x, int y) : _x(x), _y(y) {}
World::~World() { clear(); }
void World::add(Entity* entity){
_entities_tmp.push_back(entity);
}
void World::clear()
{
for (Entity* entity : _entities)
delete entity;
_entities.clear();
for (Entity* entity : _entities_tmp)
delete entity;
_entities_tmp.clear();
_sounds.clear();
}
void World::add(Configuration::Sounds sound_id){
std::unique_ptr<sf::Sound> sound(new sf::Sound(Configuration::sounds.get(sound_id)));
sound->setAttenuation(0);
sound->play();
_sounds.emplace_back(std::move(sound));
}
bool World::isCollide(const Entity& other)
{
for (Entity* entity_ptr : _entities)
if (other.isCollide(*entity_ptr))
return true;
return false;
}
int World::size() {
return _entities.size() + _entities_tmp.size();
}
int World::getX() const{
return _x;
}
int World::getY() const{
return _y;
}
const std::list<Entity*> World::getEntities() const {
return _entities;
}
void World::update(sf::Time deltaTime)
{
if (_entities_tmp.size() > 0)
_entities.merge(_entities_tmp);
for (Entity* entity_ptr : _entities)
{
Entity& entity = *entity_ptr;
entity.update(deltaTime);
sf::Vector2f pos = entity.getPosition();
if (pos.x < 0)
{
pos.x = _x;
pos.y = _y - pos.y;
}
else if (pos.x > _x)
{
pos.x = 0;
pos.y = _y - pos.y;
}
if (pos.y < 0)
pos.y = _y;
else if (pos.y > _y)
pos.y = 0;
entity.setPosition(pos);
}
const auto end = _entities.end();
for (auto it_i = _entities.begin(); it_i != end; ++it_i)
{
Entity& entity_i = **it_i;
auto it_j = it_i;
it_j++;
for (; it_j != end; ++it_j)
{
Entity& entity_j = **it_j;
if (entity_i.isAlive() && entity_i.isCollide(entity_j))
entity_i.onDestroy();
if (entity_j.isAlive() && entity_j.isCollide(entity_i))
entity_j.onDestroy();
}
}
for (auto it = _entities.begin(); it != _entities.end();)
{
if (!(*it)->isAlive()){
delete *it;
it = _entities.erase(it);
}
else ++it;
}
_sounds.remove_if([](const std::unique_ptr<sf::Sound>& sound)->
bool {
return sound->getStatus() != sf::SoundSource::Status::Playing;
});
}
void World::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
for (Entity* entity : _entities)
target.draw(*entity, states);
}
Code for world.hpp
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <list>
#include <memory>
#include "Configuration.h"
class Entity;
class World : public sf :: Drawable
{
public:
World(const World&) = delete;
World& operator=(const World&) = delete;
World(int x, int y);
~World();
void add(Entity* entity);
void clear();
bool isCollide(const Entity& other);
int size();
void add(Configuration::Sounds sound_id);
const std::list<Entity*> getEntities() const;
int getX() const;
int getY() const;
void update(sf::Time deltaTime);
private:
std::list<Entity*> _entities;
std::list<Entity*> _entities_tmp;
std::list<std::unique_ptr<sf::Sound>> _sounds;
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
const int _x;
const int _y;
};
code for Entity.h
class World;
class Entity : public sf::Drawable
{
public:
//Constructors
Entity(const Entity&) = delete;
Entity& operator= (const Entity&) = delete;
Entity(Configuration::Textures tex_id, World& world);
virtual ~Entity();
//Helpers
virtual bool isAlive() const;
const sf::Vector2f& getPosition() const;
template<typename ... Args>
void setPosition(Args&& ... args);
virtual bool isCollide(const Entity& other) const = 0;
//Updates
virtual void update(sf::Time deltaTime) = 0;
virtual void onDestroy();
protected:
friend class Meteor;
friend class Player;
friend class Saucer;
friend class ShootPlayer;
friend class ShootSaucer;
sf::Sprite _sprite;
sf::Vector2f _impulse;
World& _world;
bool _alive;
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
};
if (_entities_tmp.size() > 0)
_entities.merge(_entities_tmp);
This does not work. merge works with two sorted ranges. And your vector is not sorted. This is why you get an assertion.
If not sorting them is on purpose and you just want to concatenate the two vectors, you can do:
_entities.reserve( _entities.size() + _entities_tmp.size() );
_entities.insert( _entities.end(), _entities_tmp.begin(), _entities_tmp.end() );
I've been pulling my hair out over a certain error that seems to be plaguing my program. I've attempted to search online for cases similar to mine but I can't seem to find a way to apply the other solutions to this problem. My issue is as follows: When I initially open the program it immediately stops responding and crashes. Debugging led me to find the error in question is "0xC0000005: Access violation writing location 0xCCCCCCCC". It seems to be tied to me assigning two attributes (sku_ and name_ ) as '\0'. If I change these values to anything else such as "" or even "\0" the program runs in visual studio, but will fail to compile elsewhere. Could someone help me understand where I am going wrong?
Product.h
#ifndef SICT_Product_H__
#define SICT_Product_H__
#include "general.h"
#include "Streamable.h"
#include <cstring>
namespace sict {
class Product : public Streamable {
char sku_ [MAX_SKU_LEN + 1];
char* name_;
double price_;
bool taxed_;
int quantity_;
int qtyNeeded_;
public:
//Constructors
Product();
Product(const char* sku, const char* name1, bool taxed = true, double price = 0, int qtyNeeded =0);
Product(Product& g);
~Product();
//Putter Functions
void sku(const char* sku) { strcpy(sku_,sku); };
void price(double price) {price_ = price;};
void name(const char* name);
void taxed(bool taxed) { taxed_ = taxed; };
void quantity(int quantity) { quantity_ = quantity; };
void qtyNeeded(int qtyNeeded) { qtyNeeded_ = qtyNeeded; };
//Getter functions
const char* sku() const { return sku_; };
double price() const { return price_; };
const char* name() const { return name_; };
bool taxed() const { return taxed_; };
int quantity() const { return quantity_; };
int qtyNeeded() const { return qtyNeeded_; };
double cost() const;
bool isEmpty() const;
Product& operator=(const Product& );
bool operator==(const char* );
int operator+=(int );
int operator-=(int );
};
double operator+=(double& , const Product& );
std::ostream& operator<<(std::ostream& os, const Product& );
std::istream& operator>>(std::istream& is, Product& );
}
#endif
Product.cpp
#include <iostream>
#include <cstring>
#include "Product.h"
namespace sict {
Product::Product() {
sku_[0] = '\0';
name_[0] = '\0';
price_ = 0;
quantity_ = 0;
qtyNeeded_ = 0;
}
Product::Product(const char* sku, const char* name1, bool taxed1, double price1, int qtyNeeded1) {
strncpy(sku_, sku, MAX_SKU_LEN);
name(name1);
quantity_ = 0;
taxed(taxed1);
price(price1);
qtyNeeded(qtyNeeded1);
}
double Product::cost() const {
if (taxed_ == true) {
return (price_ * TAX) + price_;
}
else
return price_;
}
bool Product::isEmpty() const{
if (sku_ == nullptr && name_ == nullptr && quantity_ == 0 && price_ == 0 && qtyNeeded_ == 0) {
return true;
}
else
return false;
}
Product::Product(Product& ex) {
sku(ex.sku_);
price(ex.price_);
name(ex.name_);
taxed(ex.taxed_);
quantity(ex.quantity_);
qtyNeeded(ex.qtyNeeded_);
}
Product& Product::operator=(const Product& g) {
sku(g.sku_);
price(g.price_);
name(g.name_);
taxed(g.taxed_);
quantity(g.quantity_);
qtyNeeded(g.qtyNeeded_);
return *this;
}
Product::~Product() {
delete [] name_;
}
void Product::name(const char* name) {
name_ = new char [strlen(name) + 1];
strcpy(name_, name);
}
bool Product::operator==(const char* right) {
if (sku_ == right) {
return true;
}
else
return false;
}
int Product::operator+=(int g) {
quantity_ = quantity_ + g;
return quantity_;
}
int Product::operator-=(int g) {
quantity_ = quantity_ - g;
return quantity_;
}
double operator+=(double& p, const Product& right) {
p = p + (right.cost() * right.quantity());
return p;
}
std::ostream& operator<<(std::ostream& os, const Product& g) {
return g.write(os, true);
}
std::istream& operator>>(std::istream& is, Product& g) {
return g.read(is);
}
}
The General.h file referenced in the header is just a list of constant values such as the "TAX" and "MAX_SKU_LEN" values.
The Streamable header contains pure virtual functions. I will list it here in case it is needed.
Streamable.h
#ifndef SICT__Streamable_H_
#define SICT__Streamable_H_
#include <iostream>
#include <fstream>
#include "Product.h"
namespace sict {
class Streamable {
public:
virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const = 0;
virtual std::fstream& load(std::fstream& file) = 0;
virtual std::ostream& write(std::ostream& os, bool linear)const = 0;
virtual std::istream& read(std::istream& is) = 0;
};
}
#endif
Thank you very much in advance.
Product::Product() {
sku_[0] = '\0';
name_[0] = '\0'; // <---- writing via unitialized pointer
price_ = 0;
quantity_ = 0;
qtyNeeded_ = 0;
}
There's one possible source of your problems. You have defined a char pointer (a dynamic array or a C-string, that is) name_ in your class but you never allocate any memory for it in your constructor, before attempting to record a value via the pointer. Naturally, you get a write access violation.
Before assigning the value to char at index [0] you need to first allocate space for at least one element in your string, e.g. by doing name_ = new char [1]. Alternatively, you may choose to initialize the pointer itself to NULL (or nullptr) and use that to indicate that name_ has not yet been set.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 8 years ago.
Improve this question
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#ifndef ViasLigacaoAuto_
#define ViasLigacaoAuto_
#include <iostream>
#include <string>
using namespace std;
#include "LocInteresse.h"
#include "ViasLigacao.h"
class ViasLigacaoAuto : public ViasLigacao
{
private:
float precoportagem;
public:
ViasLigacaoAuto();
ViasLigacaoAuto(LocInteresse* &locInteresse1,LocInteresse* &locInteresse2,string codigodavia,int totalkms,int tempomedio,float precoportagem);
ViasLigacaoAuto(string codigodavia,int totalkms,int tempomedio,float precoportagem);
ViasLigacaoAuto(const ViasLigacaoAuto& va);
~ViasLigacaoAuto();
float getPrecoportagem()const;
void setPrecoportagem(float precoportagem);
void listar()const;
ViasLigacao* ViasLigacaoAuto :: clone() { return new ViasLigacaoAuto(*this);} //criar uma copia de um objecto que ja existe
ViasLigacaoAuto& operator=(const ViasLigacaoAuto &va);
virtual void ViasLigacaoAuto:: escrever(ostream &out) const;
};
//constructores
ViasLigacaoAuto :: ViasLigacaoAuto() : ViasLigacao()
{
this->precoportagem=-1;
}
ViasLigacaoAuto :: ViasLigacaoAuto(LocInteresse* &locInteresse1,LocInteresse* &locInteresse2,string codigodavia,int totalkms,int tempomedio,float precoportagem) :
ViasLigacao(locInteresse1,locInteresse2,codigodavia,totalkms,tempomedio)
{
(*this).setPrecoportagem(precoportagem);
}
ViasLigacaoAuto::ViasLigacaoAuto(const ViasLigacaoAuto& va) : ViasLigacao(va)
{
this->precoportagem=va.precoportagem;
}
ViasLigacaoAuto :: ~ViasLigacaoAuto()
{
}
void ViasLigacaoAuto::setPrecoportagem(float precoportagem)
{
(*this).precoportagem=precoportagem;
}
float ViasLigacaoAuto::getPrecoportagem()const{
return (*this).precoportagem;
}
void ViasLigacaoAuto :: listar() const
{
}
ViasLigacaoAuto& ViasLigacaoAuto::operator=(const ViasLigacaoAuto &va)
{
if(this!=&va)
{
precoportagem=va.precoportagem;
ViasLigacao::operator=(va);
}
return (*this);
}
void ViasLigacaoAuto :: escrever(ostream &out) const
{
out << "Autoestrada " << endl;
ViasLigacao::escrever(out); //atributos herdados da classe viasligacao
out << "Preco da portagem: " << precoportagem << endl;
}
ostream& operator<<(ostream &o, const ViasLigacaoAuto &va)
{
va.escrever(o);
return o;
}
#endif
*
#pragma once
#ifndef _ApViasLigacao_
#define _ApViasLigacao_
#include <ostream>
using namespace std;
#include "ViasLigacao.h"
#include "ViasLigacaoAuto.h"
#include "ViasLigacaoNacional.h"
#include "Teste.h"
#include "LocInteresse.h"
#include "LocInteresseCult.h"
#include "LocInteresseNat.h"
//---------Classe apontador para ViasLigacao---------
class ApViasLigacao {
private:
ViasLigacao *apvl;
enum TipoComparacao { KMS , CUSTO ,TEMPO};
static TipoComparacao tipoComparacao;
public:
static void setComparacaoKMS();
static void setComparacaoCUSTO();
static void setComparacaoTEMPO();
int getTotalkms() const;
virtual float getPrecoportagem() const;
int getTempomedio()const;
LocInteresse* getLocIni();
void setLocIni(LocInteresse);
LocInteresse* getLocFim();
void setLocFim(LocInteresse);
ApViasLigacao();
ApViasLigacao(ViasLigacao* &vl);
ApViasLigacao(string codigodavia,int totalkms,int tempomedio,float precoportagem);
ApViasLigacao(string codigodavia,int totalkms,int tempomedio,string pavimento);
ApViasLigacao(const ApViasLigacao &vl);
~ApViasLigacao();
const ApViasLigacao & operator=(const ApViasLigacao &vl);
bool operator >(const ApViasLigacao &vl) const;
bool operator <(const ApViasLigacao &vl) const;
bool operator ==(const ApViasLigacao &vl) const;
ApViasLigacao operator+(const ApViasLigacao &vl);
const ApViasLigacao & operator+=(const ApViasLigacao &vl);
void write(ostream &out) const;
};
ApViasLigacao::TipoComparacao ApViasLigacao::tipoComparacao=ApViasLigacao::TipoComparacao::KMS;
void ApViasLigacao::setComparacaoKMS() {
tipoComparacao=TipoComparacao::KMS;
}
void ApViasLigacao::setComparacaoCUSTO() {
tipoComparacao=TipoComparacao::CUSTO;
}
void ApViasLigacao::setComparacaoTEMPO(){
tipoComparacao=TipoComparacao::TEMPO;
}
int ApViasLigacao::getTotalkms() const {
return apvl->getTotalkms();
}
float ApViasLigacao::getPrecoportagem() const {
return apvl->getPrecoportagem();
}
int ApViasLigacao::getTempomedio() const {
return apvl->getTempomedio();
}
ApViasLigacao::ApViasLigacao() {
this->apvl = new ViasLigacaoAuto();
}
ApViasLigacao::ApViasLigacao(string codigodavia,int totalkms,int tempomedio,float precoportagem) {
apvl = new ViasLigacaoAuto(codigodavia, totalkms,tempomedio, precoportagem);
}
ApViasLigacao::ApViasLigacao(string codigodavia,int totalkms,int tempomedio,string pavimento) {
apvl = new ViasLigacaoNacional(codigodavia,totalkms,tempomedio,pavimento);
}
ApViasLigacao::ApViasLigacao(ViasLigacao* &vl) {
this->apvl = vl->clone();
}
ApViasLigacao::ApViasLigacao(const ApViasLigacao &vl) {
this->apvl = vl.apvl->clone();
}
ApViasLigacao::~ApViasLigacao() {
delete apvl;
}
//bool compara(int km1, int km2, double c1, double c2, std::
bool ApViasLigacao::operator >(const ApViasLigacao &vl) const {
if (tipoComparacao==TipoComparacao::KMS) return (*this).getTotalkms() > vl.getTotalkms();
if (tipoComparacao==TipoComparacao::CUSTO){
if((*this).getPrecoportagem() == vl.getPrecoportagem()){
return (*this).getTotalkms() > vl.getTotalkms();
}
return (*this).getPrecoportagem() > vl.getPrecoportagem();
}
return (*this).getTempomedio() > vl.getTempomedio();
}
bool ApViasLigacao::operator <(const ApViasLigacao &vl) const {
if (tipoComparacao==TipoComparacao::KMS) return (*this).getTotalkms() < vl.getTotalkms();
if (tipoComparacao==TipoComparacao::CUSTO){
if((*this).getPrecoportagem() == vl.getPrecoportagem()){
return (*this).getTotalkms() < vl.getTotalkms();
}
return (*this).getPrecoportagem() < vl.getPrecoportagem();
}
return (*this).getTempomedio() < vl.getTempomedio();
}
bool ApViasLigacao::operator ==(const ApViasLigacao &vl) const {
if (tipoComparacao==TipoComparacao::KMS) return (*this).getTotalkms() == vl.getTotalkms();
if (tipoComparacao==TipoComparacao::CUSTO) return (*this).getPrecoportagem() == vl.getPrecoportagem();
return (*this).getTempomedio() == vl.getTempomedio();
}
ApViasLigacao ApViasLigacao::operator+(const ApViasLigacao &vl) {
return ApViasLigacao("", (*this).getTotalkms()+vl.getTotalkms(), (*this).getTempomedio()+vl.getTempomedio(), (*this).getPrecoportagem()+vl.getPrecoportagem());
}
const ApViasLigacao & ApViasLigacao::operator+=(const ApViasLigacao &vl) {
this->apvl->setTotalkms(this->apvl->getTotalkms()+vl.apvl->getTotalkms());
this->apvl->setTempomedio(this->apvl->getTempomedio()+vl.apvl->getTempomedio());
if (typeid(*apvl)==typeid(ViasLigacaoAuto)) {
ViasLigacaoAuto *vla = (ViasLigacaoAuto *)this->apvl;
vla->setPrecoportagem(vla->getPrecoportagem()+vl.apvl->getPrecoportagem());
}
return *this;
}
const ApViasLigacao & ApViasLigacao::operator=(const ApViasLigacao &vl) {
this->apvl = vl.apvl->clone();
return *this;
}
void ApViasLigacao::write(ostream &out) const {
out << *apvl;
}
ostream &operator <<(ostream &out, const ApViasLigacao &vl)
{
vl.write(out);
return out;
}
#endif
*
#define _CRT_SECURE_NO_WARNINGS
#ifndef ViasLigacao_
#define ViasLigacao_
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
#include "LocInteresse.h"
class ViasLigacao
{
private:
LocInteresse locInteresse1, locInteresse2;
string codigodavia;
int totalkms;
int tempomedio;
public:
ViasLigacao();
ViasLigacao(LocInteresse* locInteresse1,LocInteresse* locInteresse2,string codigodavia,int kms,int tempo);
ViasLigacao(const ViasLigacao &v);
virtual ~ViasLigacao(); //destructor
void listar()const;
virtual ViasLigacao* clone()const;
LocInteresse* getLocInteresse1();
void setLocInteresse1(LocInteresse);
LocInteresse* getLocInteresse2();
void setLocInteresse2(LocInteresse);
string getCodigodavia()const;
void setCodigodavia(string codigodavia);
int getTotalkms()const;
void setTotalkms(int kms);
int getTempomedio()const;
void setTempomedio(int tempo);
virtual float getPrecoportagem() const;
const ViasLigacao & operator=(const ViasLigacao &v);
bool operator>(const ViasLigacao &v) const;
bool operator==(const ViasLigacao &v) const;
bool operator <(const ViasLigacao &v) const;
bool operator<=(const ViasLigacao &v)const;
ViasLigacao operator+(const ViasLigacao &v);
const ViasLigacao & operator+=(const ViasLigacao &v);
void escrever(ostream &out) const; // só se mete VIRTUAL quando sao subclasses
};
ViasLigacao::ViasLigacao()
{
codigodavia = " ";
totalkms= -1;
tempomedio=-1;
}
ViasLigacao::ViasLigacao(LocInteresse* LocInteresse1, LocInteresse* LocInteresse2,string codigodavia, int totalkms,int tempomedio)
{
//this->locInteresse1=LocInteresse1;
// this->locInteresse2=LocInteresse2;
this->codigodavia = codigodavia;
this->totalkms = totalkms;
this->tempomedio=tempomedio;
}
ViasLigacao::ViasLigacao(const ViasLigacao & v)
{
this->locInteresse1=v.locInteresse1;
this->locInteresse2=v.locInteresse2;
this->codigodavia = v.codigodavia;
this->totalkms = v.totalkms;
this->tempomedio= v.tempomedio;
}
ViasLigacao::~ViasLigacao()
{
}
//set's e get's
void ViasLigacao::setLocInteresse1(LocInteresse locInteresse1)
{
locInteresse1 = locInteresse1;
}
LocInteresse* ViasLigacao::getLocInteresse1(){
return &locInteresse1;
}
void ViasLigacao::setLocInteresse2(LocInteresse locInteresse2)
{
locInteresse2 = locInteresse2;
}
LocInteresse* ViasLigacao::getLocInteresse2(){
return &locInteresse2;
}
void ViasLigacao::setCodigodavia(string codigodavia)
{
this->codigodavia = codigodavia;
}
string ViasLigacao::getCodigodavia()const{
return this->codigodavia;
}
void ViasLigacao::setTotalkms(int totalkms)
{
this->totalkms = totalkms;
}
int ViasLigacao::getTotalkms()const
{
return this->totalkms;
}
void ViasLigacao::setTempomedio(int tempomedio)
{
this->tempomedio = tempomedio;
}
int ViasLigacao::getTempomedio()const
{
return this->tempomedio;
}
ViasLigacao* ViasLigacao ::clone() const{
return new ViasLigacao(*this);
}
float ViasLigacao::getPrecoportagem() const{
return 0;
}
bool ViasLigacao :: operator>(const ViasLigacao &v)const{
if(totalkms > v.totalkms)
{
return true;
}
return false;
}
bool ViasLigacao :: operator==(const ViasLigacao &v)const{
if(totalkms > v.totalkms)
{
return true;
}
return false;
}
const ViasLigacao& ViasLigacao:: operator= (const ViasLigacao& v){
if(&v != this){
(*this)=ViasLigacao(v);
}
return *this;
}
ostream& operator<<(ostream &o, const ViasLigacao &v)
{
v.escrever(o);
return o;
}
void ViasLigacao :: escrever(ostream &out) const
{
out << "Local de Interesse inicial:" << locInteresse1 << endl;
out << "Local de Interesse final:" << locInteresse2 << endl;
out << "Via de ligação: " << endl;
out << "Codigo da via: " << codigodavia << endl;
out << "Total de kms: " << totalkms << endl;
out << "Tempo medio: " << tempomedio << endl;
}
#endif
can anyone help?
i get this error
Error 6 error LNK2019: unresolved external symbol "public: __thiscall ViasLigacaoAuto::ViasLigacaoAuto(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,int,float)" (??0ViasLigacaoAuto##QAE#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##HHM#Z) referenced in function "public: __thiscall ApViasLigacao::ApViasLigacao(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,int,float)" (??0ApViasLigacao##QAE#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##HHM#Z) C:\Users\joaopedro\Source\Repos\1110830_1121107_esinf\MapaDigital\Main.obj MapaDigital
It's saying it can't find the third constructor you've declared for ViasLigacaoAuto (the one that takes string, int, int, float) - and indeed, that constructor doesn't seem to be defined in your code. You need to define it.
(Just occasionally the compiler/linker error messages tell you what the problem actually is.)