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.)
Related
I need to sort a vector of pointers with this test data.
main.cpp
#include "cart.h"
int main()
{
Cart cart;
cart.addItem("Desktop", 125.34f);
cart.addItem("Iphone", 46.274f);
cart.addItem("Pen", 118.99f);
cart.addItem("Ruler", 41.34f);
cart.addItem("Printer", 2.99f);
cart.printSortedItems();
cart.destroy();
}
item.h
#include <string>
#include <tuple>
class Item
{
private:
Item(const std::string& name, const ItemType& itemType, const float& price);
~Item();
std::string m_name;
float m_price;
public:
static Item *getInstance(const std::string& name, const float& price);
bool operator>(const Item& item2) const;
void print() const;
};
item.cpp
#include "item.h"
#include <iostream>
Item::Item(const std::string& name, const float& price)
{
m_name = name;
m_price = price;
}
Item::~Item()
{
}
Item *Item::getInstance(const std::string& name, const float& price)
{
return new Item(name, price);
}
bool Item::operator>(const Item & item2) const
{
if (m_name > item2.m_name) {
return true;
}
if (m_name == item2.m_name && m_price > item2.m_price) {
return true;
}
return false;
}
void Item::print() const
{
std::cout << "Item name: " << m_name << " Item price: "<< m_price << std::endl;
}
cart.h
#include <vector>
class Cart
{
public:
Cart();
~Cart();
void addItem(const std::string& name, const float& price);
void printSortedItems();
void sortItems();
void destroy();
private:
std::vector<Item*> m_itemList = {};
};
cart.cpp
#include "cart.h"
#include <iostream>
#include <algorithm>
Cart::Cart(){}
Cart::~Cart(){}
void Cart::addItem(const std::string& name, const float& price)
{
Item *newItem = Item::getInstance(name, itemType, price);
m_itemList.push_back(newItem);
}
void Cart::sortItems()
{
for (size_t i = 0; i < m_itemList.size()-1; i++)
{
for (size_t j = i + 1; j < m_itemList.size(); j++)
{
if (m_itemList[i] > m_itemList[j])
{
std::swap(m_itemList[i], m_itemList[j]);
}
}
}
}
void Cart::printSortedItems()
{
sortItems();
std::cout << "Items" << std::endl;
for (size_t i = 0; i < m_itemList.size(); i++)
{
m_itemList[i]->print();
}
std::cout << std::endl;
}
void Cart::destroy()
{
for (size_t i = 0; i < m_itemList.size(); i++)
{
delete m_itemList[i];
m_itemList[i] = nullptr;
}
}
In function Cart::sortItems(), I compare m_itemList[i] and m_itemList[j], these are both pointers to instance of Item. Theoretically, if I set a break point in bool Item::operator>(const Item & item2) const, it should be hit. But in this case, the break point is not hit, and therefore, the result after sorting is wrong. Could you guys tell me where I am wrong?
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'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.
edit*: The full error message: test_huffman.cpp: In member function 'virtual void HuffmanTest_Test_Test::TestBody()'
I'm trying to write a google test for some cpp code. I'm getting an error and I'm not sure how to fix it. This is the error: test_huffman.cpp: In member function 'virtual void HuffmanTest_Test_Test::TestBody()'. The only answer I found online is that I need an argument list? Not sure where to go from here. The huffman.h/.cpp are probably not necessary but figured I'd share them (no I didn't write them they are open source);
Here is the code that I get the error when I compile (w/ gcc):
#include "gtest/gtest.h"
#include "huffman.h"
TEST(HuffmanTest, Test)
{
char* words[3];
words[0] = "one\0";
words[1] = "two\0";
words[2] = "three\0";
int frequencies[UniqueSymbols] = {0};
for(int i = 1; i < 3; i++)
{
const char* ptr = words[i];
while (*ptr != '\0')
++frequencies[*ptr++];
}
INode* root = BuildTree(frequencies);
HuffCodeMap codes;
GenerateCodes(root, HuffCode(), codes);
delete root;
EXPECT_FALSE(codes.empty());
}
Huffman.h (open source):
#ifndef huffman_h_INCLUDED
#define huffman_h_INCLUDED
#include <iostream>
#include <queue>
#include <map>
#include <climits> // for CHAR_BIT
#include <iterator>
#include <algorithm>
const int UniqueSymbols = 1 << CHAR_BIT;
typedef std::vector<bool> HuffCode;
typedef std::map<char, HuffCode> HuffCodeMap;
class INode
{
public:
const int f;
virtual ~INode();
protected:
INode(int f);
};
class InternalNode : public INode
{
public:
INode *const left;
INode *const right;
InternalNode(INode* c0, INode* c1);
~InternalNode();
};
class LeafNode : public INode
{
public:
const char c;
LeafNode(int f, char c);
};
struct NodeCmp
{
bool operator()(const INode* lhs, const INode* rhs) const;
};
INode* BuildTree(const int (&frequencies)[UniqueSymbols]);
void GenerateCodes(const INode* node, const HuffCode& prefix, HuffCodeMap& outCodes);
#endif // huffman_h_INCLUDED
huffman.cpp (open source):
#include "huffman.h"
INode :: ~INode()
{
}
INode :: INode(int f)
: f(f)
{
}
InternalNode :: InternalNode(INode* c0, INode* c1)
: INode(c0->f + c1->f), left(c0), right(c1)
{
}
InternalNode :: ~InternalNode()
{
delete left;
delete right;
}
LeafNode :: LeafNode(int f, char c)
: INode(f), c(c)
{
}
bool NodeCmp :: operator()(const INode* lhs, const INode* rhs) const { return lhs->f > rhs->f; }
INode* BuildTree(const int (&frequencies)[UniqueSymbols])
{
std::priority_queue<INode*, std::vector<INode*>, NodeCmp> trees;
for (int i = 0; i < UniqueSymbols; ++i)
{
if(frequencies[i] != 0)
trees.push(new LeafNode(frequencies[i], (char)i));
}
while (trees.size() > 1)
{
INode* childR = trees.top();
trees.pop();
INode* childL = trees.top();
trees.pop();
INode* parent = new InternalNode(childR, childL);
trees.push(parent);
}
return trees.top();
}
void GenerateCodes(const INode* node, const HuffCode& prefix, HuffCodeMap& outCodes)
{
if (const LeafNode* lf = dynamic_cast<const LeafNode*>(node))
{
outCodes[lf->c] = prefix;
}
else if (const InternalNode* in = dynamic_cast<const InternalNode*>(node))
{
HuffCode leftPrefix = prefix;
leftPrefix.push_back(false);
GenerateCodes(in->left, leftPrefix, outCodes);
HuffCode rightPrefix = prefix;
rightPrefix.push_back(true);
GenerateCodes(in->right, rightPrefix, outCodes);
}
}
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&.