How to show double and integers in a TableView in QT - c++

I have a table with 5 rows and 5 columns. I am trying to insert double numbers and integer numbers. On column 1 and 2 (double numbers) and column 3 and 4 (integer) and last column images.
I am trying to figure out what the error is in the code I wrote:
#ifndef ITEMROI_H
#define ITEMROI_H
#include <QObject>
#include <QString>
class itemRoi
{
public:
itemRoi(int &size, const QString &threeDLocation, const QString &concavity,
int &color, const QByteArray &imagesData = QByteArray());
int size() const { return mSize; }
QString threeDLocation() const { return m3DLocation; }
QString concavity() const { return mConcavity; }
int color() const { return mColor; }
QByteArray imagesData() const { return mImagesData; }
private:
int mSize;
double m3DLocation;
double mConcavity;
int mColor;
QByteArray mImagesData;
};
#endif // ITEMROI_H
I am getting errors on the following parts:
QString threeDLocation() const { return m3DLocation; }
QString concavity() const { return mConcavity; }
Any idea? Thanks

Related

Qt C++, unable to initialize QMetaObject in order to use Meta Objects to write XML string/file

I am writing a program where I want to use QMetaObject to write Data from a QList to an xml string/file. However, when I go to initialize the QMetaObject in the function to write the xml, it gives me an error.
Let me quickly post my code:
//container.h, basic data class
#include <QObject>
class Container : public QObject
{
Q_OBJECT
public:
explicit Container(QObject *parent = nullptr);
virtual int getLen() = 0;
virtual int getHei() = 0;
virtual int getBre() = 0;
virtual int getDia() = 0;
virtual int getWei() = 0;
virtual int getVol() = 0;
virtual QString getCode() = 0;
};
//box.h, first concrete class, am intending on adding a second later
#include <container.h>
#include <QObject>
#include <QString>
class Box : public Container
{
Q_OBJECT
Q_PROPERTY(QString code READ getCode)
Q_PROPERTY(int height READ getHei)
Q_PROPERTY(int weight READ getWei)
Q_PROPERTY(int length READ getLen)
public:
explicit Box(QString C, int l, int b, int h, int w);
int getLen();
int getHei();
int getBre();
int getDia();
int getWei();
int getVol();
QString getCode();
private:
QString Code;
int length, breadth, height;
int weight;
int volume;
};
//box.cpp
#include "box.h"
Box::Box(QString C, int l, int b, int h, int w)
: Code(C),
length(l),
breadth(b),
height(h),
weight(w)
{
}
int Box::getLen()
{
return length;
}
int Box::getHei()
{
return height;
}
int Box::getBre()
{
return breadth;
}
int Box::getDia()
{
return 0;
}
int Box::getWei()
{
return weight;
}
int Box::getVol()
{
return length * height * breadth;
}
QString Box::getCode()
{
return Code;
}
//pallet.h, a class that holds a QList of Objects of type 'Container'
#include "box.h"
#include "container.h"
#include <QList>
class Pallet
{
public:
Pallet();
void add_to_Container_List(QString C, int l, int b, int h, int w); //Box
void add_to_Container_List(Container *X); //Container Item
QList<Container *>* get_Container_List() const;
void setPallet_Number(int num);
int getPallet_Number();
int getPallet_Weight();
int getPallet_Volume();
private:
QList<Container*> *CList;
int Pallet_Number;
int PWeight;
int PVolume;
};
//pallet.cpp
#include "pallet.h"
#include <QDebug>
Pallet::Pallet(): Pallet_Number(0), PWeight(0), PVolume(0)
{
}
void Pallet::add_to_Container_List(QString C, int l, int b, int h, int w)
{
Container *Xn = new Box(C, l, b, h, w);
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
void Pallet::add_to_Container_List(QString C, int h, int d, int w)
{
Container *Xn = new Cylinder(C, h, d, w);
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
QList<Container *> *Pallet::get_Container_List() const
{
return CList;
}
void Pallet::add_to_Container_List(Container *X)
{
Container *Xn = X;
PWeight += Xn->getWei();
PVolume += Xn->getVol();
CList->append(Xn);
}
void Pallet::setPallet_Number(int num)
{
Pallet_Number = num;
}
int Pallet::getPallet_Number()
{
return Pallet_Number;
}
int Pallet::getPallet_Weight()
{
return PWeight;
}
int Pallet::getPallet_Volume()
{
return PVolume;
}
Lastely, I also have a MainWindow class that holds a QList of type 'Pallet', a GUI that allows you to create a QList of type 'Container', and then allocate those items to separate Pallets, but this is irrelevant to the problem.
The problem comes when I try to compile the next class I created:
//write_xml.h, the purpose is simply to take a QList of type 'Pallet' and turn it into a xml string
#include "pallet.h"
class Write_XML
{
public:
Write_XML();
QString Write_XML_String(QList<Pallet*> PList);
};
//write_xml.cpp
#include "write_xml.h"
#include <QMetaObject>
#include <QXmlStreamWriter>
Write_XML::Write_XML()
{
}
QString Write_XML::Write_XML_String(QList<Pallet *> PList)
{
QMetaObject *meta;
int numProperties;
QMetaProperty *meta_prop;
QString XString;
QXmlStreamWriter writing(&XString);
writing.setAutoFormatting(true);
writing.writeStartElement("Pallets"); //Pallet
writing.writeAttribute("Number_of_Pallets", QString::number(PList.length()));
foreach(auto P, PList)
{
writing.writeStartElement("Pallet");
writing.writeAttribute("Number",QString::number(P->getPallet_Number()));
writing.writeAttribute("Weight",QString::number(P->getPallet_Weight()));
writing.writeAttribute("Volume",QString::number(P->getPallet_Volume()));
foreach(auto *C, *P->get_Container_List())
{
meta = C->metaObject(); //problem encountered here.
// numProperties = meta->propertyCount();
}
writing.writeEndElement(); //end Pallet
}
writing.writeEndElement(); //end Pallets
return XString;
}
When Compiling, I get the following error message:
invalid conversion from 'const QMetaObject*' to 'QMetaObject*' [-fpermissive]
Where have I made my mistake and how can I fix it?

qspinbox64 in QT5.15.2

I tried to create a qspinbox64 as suggested in
64bit int Spin Box in QT
qspinbox64.h
#define QSPINBOX64_H
#include <QtGui>
#include <QtWidgets>
namespace Ui {
class QSpinBox64;
}
class QSpinBox64Private;
class Q_WIDGETS_EXPORT QSpinBox64 : public QAbstractSpinBox//QSpinBox
{
Q_OBJECT
Q_PROPERTY(int64_t minimum READ minimum WRITE setMinimum)
Q_PROPERTY(int64_t maximum READ maximum WRITE setMaximum)
Q_PROPERTY(int64_t value READ value WRITE setValue NOTIFY valueChanged USER true)
int64_t m_minimum;
int64_t m_maximum;
int64_t m_value;
public:
explicit QSpinBox64(QWidget *parent = nullptr)
{
connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
}
~QSpinBox64()
{
}
int64_t value() const
{
return m_value;
}
int64_t minimum() const
{
return m_minimum;
}
int64_t maximum() const
{
return m_maximum;
}
void setMinimum(int64_t min)
{
m_minimum = min;
}
void setMaximum(int64_t max)
{
m_maximum = max;
}
void setRange(int64_t min, int64_t max)
{
setMinimum(min);
setMaximum(max);
}
virtual void stepBy(int steps)
{
auto new_value = m_value;
if (steps < 0 && new_value + steps > new_value) {
new_value = std::numeric_limits<qlonglong>::min();
}
else if (steps > 0 && new_value + steps < new_value) {
new_value = std::numeric_limits<qlonglong>::max();
}
else {
new_value += steps;
}
lineEdit()->setText(textFromValue(new_value));
setValue(new_value);
}
protected:
virtual QValidator::State validate(QString &text, int &pos) const
{
//return validator->validate(text, pos);
bool ok;
int64_t val = text.toLongLong(&ok);
if (!ok)
return QValidator::Invalid;
if (val < m_minimum || val > m_maximum)
return QValidator::Invalid;
return QValidator::Acceptable;
}
virtual int64_t valueFromText(const QString &text) const
{
bool ok;
return text.toLongLong(&ok, 10);
}
virtual QString textFromValue(int64_t value) const
{
return QString::number(value, 10).toUpper();
}
virtual QAbstractSpinBox::StepEnabled stepEnabled() const;
public
Q_SLOTS:
void setValue(int64_t val)
{
if (m_value != val) {
lineEdit()->setText(textFromValue(val));
m_value = val;
}
}
void onEditFinished()
{
QString input = lineEdit()->text();
int pos = 0;
if (QValidator::Acceptable == validate(input, pos))
setValue(valueFromText(input));
else
lineEdit()->setText(textFromValue(m_value));
}
Q_SIGNALS:
void valueChanged(int64_t v);
private:
Ui::QSpinBox64 *ui;
Q_DISABLE_COPY(QSpinBox64)
Q_DECLARE_PRIVATE(QSpinBox64)
};
#endif
main.cpp
#include <QHBoxLayout>
#include "qspinbox64.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSpinBox64 spinBox;
spinBox.setWindowTitle(QObject::tr("QSpinBox64"));
spinBox.show();
return app.exec();
}
An error occurs after compilation:
G:\proj\build-qspinbox64-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\moc_qspinbox64.cpp:141:
error: C2491: 'QSpinBox64::staticMetaObject': definition of dllimport static data member not allowed
What should I do to avoid this error?
The culprit is Q_WIDGETS_EXPORT, defined in qtwidgetsglobal.h
# if defined(QT_BUILD_WIDGETS_LIB)
# define Q_WIDGETS_EXPORT Q_DECL_EXPORT
# else
# define Q_WIDGETS_EXPORT Q_DECL_IMPORT
# endif
You should declare QT_BUILD_WIDGETS_LIB in your project by adding this line to the .pro file
DEFINES += QT_BUILD_WIDGETS_LIB
Some side notes:
You are missing the header guard #ifndef QSPINBOX64_H
The constructor should call the base class constructor and set the min/max as instructed in the original post.
stepEnabled() needs to be implemented
explicit QSpinBox64(QWidget *parent = nullptr) : QAbstractSpinBox{parent}
{
setMaximum(std::numeric_limits<int64_t>::max());
setMinimum(std::numeric_limits<int64_t>::min());
connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
}
virtual QAbstractSpinBox::StepEnabled stepEnabled() const
{
return QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
}

Vector member always zero size on call to member function that uses push_back to add to the vector member

What I am trying to do is add cards to a vector that is to be a Blackjack hand, but each time I enter the function that uses push_back to add a card to the vector, the vector starts out empty. The problem is in my Hand class in the addCardToHand function, and the same issue is present in the same class in my showHand function. I have whittled the code down as much as I could but still present a full working version with the issue. I cannot figure out why my Hand class treats the hand as brand new every time I call a function in the class. Please advise.
// Card.h
#ifndef CARD_H
#define CARD_H
#include <string>
#include <array>
class Card {
private:
int rank;
int suit;
int hardValue;
int softValue;
static const std::array<std::string,14> ranks;
static const std::array<std::string,5> suits;
public:
Card();
Card(int rank, int suit);
int getHardValue() const;
int getSoftValue() const;
std::string toString() const;
};
#endif
// Card.cpp
#include "Card.h"
const std::array<std::string,14> Card::ranks {"","A","2","3","4","5","6","7","8","9","10","J","Q","K"};
const std::array<std::string,5> Card::suits {"","C","D","H","S"};
Card::Card() : rank(0), suit(0) {
hardValue = 0;
softValue = 0;
}
Card::Card(int rank, int suit) : rank(rank), suit(suit) {
if (rank == 1) {
hardValue = 1;
softValue = 11;
}
else if (rank <= 10) {
hardValue = rank;
softValue = rank;
}
else {
hardValue = 10;
softValue = 10;
}
}
int Card::getHardValue() const {
return hardValue;
}
int Card::getSoftValue() const {
return softValue;
}
std::string Card::toString() const {
return ranks[rank] + suits[suit];
}
// Shoe.h
#ifndef SHOE_H
#define SHOE_H
#include <vector>
#include <random>
#include "Card.h"
class Shoe {
private:
int numDecksInShoe;
std::vector<Card> shoe;
static int currentCard;
static int maxDealCard;
static const unsigned long int seed;
static std::mt19937 randEng;
void renewShoe();
public:
Shoe();
explicit Shoe(int numDecksInShoe);
std::vector<Card> getShoe() const;
int getCurrentCard() const;
int getMaxDealCard() const;
void shuffle();
Card dealCard();
};
#endif
// Shoe.cpp
#include <ctime>
#include "Shoe.h"
const unsigned long int Shoe::seed = static_cast<unsigned long int>(std::time(nullptr));
std::mt19937 Shoe::randEng(seed);
int Shoe::currentCard = 0;
int Shoe::maxDealCard = 51;
Shoe::Shoe() {
}
Shoe::Shoe(int decksInShoe) {
numDecksInShoe = decksInShoe;
int count = 0;
for (int i = 0; i < numDecksInShoe; i++) {
for (int suit = 4; suit >= 1; suit--) {
for (int rank = 1; rank <= 13; rank++) {
Card card(rank,suit);
shoe.push_back(card);
count += 1;
}
}
}
currentCard = 0;
maxDealCard = count - 1;
}
std::vector<Card> Shoe::getShoe() const {
return shoe;
}
int Shoe::getCurrentCard() const {
return currentCard;
}
int Shoe::getMaxDealCard() const {
return maxDealCard;
}
void Shoe::shuffle() {
Card temp;
std::uniform_int_distribution<int> deckDist(0,numDecksInShoe*52-1);
int index;
for (int i = 0; i < numDecksInShoe*52; i++) {
do {
index = deckDist(randEng);
} while (index == i);
temp = shoe[index];
shoe[index] = shoe[i];
shoe[i] = temp;
}
std::uniform_int_distribution<int> maxDeal(10,41);
int tempMax = (numDecksInShoe-1)*52 - 1;
maxDealCard = tempMax + 51 - maxDeal(randEng);
}
Card Shoe::dealCard() {
if (currentCard == maxDealCard) {
renewShoe();
}
Card dealCard = shoe[currentCard];
currentCard += 1;
return dealCard;
}
void Shoe::renewShoe() {
Shoe newShoe(numDecksInShoe);
shoe = newShoe.getShoe();
shuffle();
}
here is my Hand class
// Hand.h
#ifndef HAND_H
#define HAND_H
#include <vector>
#include <string>
#include "Card.h"
class Hand {
private:
std::vector<Card> hand;
public:
Hand();
std::vector<Card> getHand() const;
void addCardToHand(Card card);
void clearHand();
Card revealBottomCard();
std::string showHand() const;
std::string peakHand() const;
};
#endif
// Hand.cpp
#include <iostream>
#include "Hand.h"
Hand::Hand() {
}
std::vector<Card> Hand::getHand() const {
return hand;
}
void Hand::addCardToHand(Card card) {
std::cout << card.toString() << std::endl;
hand.push_back(card);
}
void Hand::clearHand() {
hand.clear();
}
std::string Hand::showHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 1; i--) {
returnString += hand[i].toString() + "\n";
}
returnString += "XX\n";
return returnString;
}
std::string Hand::peakHand() const {
std::string returnString = "";
for (int i = hand.size()-1; i >= 0; i--) {
returnString += hand[i].toString() + "\n";
}
return returnString;
}
here is the Table class that has the code that calls the Hand class functions
// Table.h
#ifndef TABLE_H
#define TABLE_H
#include "Shoe.h"
#include "Player.h"
class Table {
private:
Shoe shoe;
public:
explicit Table(Shoe shoe);
Shoe getShoe() const;
void clearHand(std::vector<Player> players);
void dealHand(std::vector<Player> players);
};
#endif
// Table.cpp
#include <iostream>
#include "Table.h"
Table::Table(Shoe shoe) : shoe(shoe) {
}
Shoe Table::getShoe() const {
return shoe;
}
void Table::clearHand(std::vector<Player> players) {
for (Player &player : players) {
player.getHand().clearHand();
}
}
void Table::dealHand(std::vector<Player> players) {
for (int i = 0; i <= 1; i++) {
for (Player &player : players) {
player.getHand().addCardToHand(shoe.dealCard());
}
}
}
// Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include "Hand.h"
class Player {
private:
std::string name;
Hand hand;
double money;
public:
explicit Player(std::string name, double money = 1000.0);
std::string getName() const;
Hand getHand() const;
double getMoney() const;
};
#endif
// Player.cpp
#include "Player.h"
Player::Player(std::string name, double money) : name(name), money(money) {
}
std::string Player::getName() const {
return name;
}
Hand Player::getHand() const {
return hand;
}
double Player::getMoney() const {
return money;
}
and finally here is a short driver that runs and displays the issue
// blackjack testing
#include <iostream>
#include "Player.h"
#include "Table.h"
int main() {
std::vector<Player> players {Player("Tom",1500.0),Player("Sue"),Player("Dave")};
Shoe shoe1(6);
Table table1(shoe1);
table1.dealHand(players);
for (Player player : players) {
std::cout << player.getName() << "'s hand\n";
std::cout << player.getHand().showHand() << "\n\n";
}
}
The output is below. I printed out the cards that were added to the hand vector (and then 'forgotten') and below that above the XX's, if everything were to work correctly you should see the 4, 5 and 6 of spades since I did not shuffle the deck. The XX's are to simulate face down bottom card.
AS
2S
3S
4S
5S
6S
Tom's hand
XX
Sue's hand
XX
Dave's hand
XX
Sorry for dumping all this code in here, but I wanted to provide a full working solution and this is as small as I could get it. Thanks for any help.
player.getHand().addCardToHand(...);
player.getHand() returns a temporary Hand object that's a copy of player.hand. Then you add a card to that temporary object. Then that temporary object dies, added card and all. player.hand remains unchanged. This line of code is an elaborate no-op.
To add on #Igor's answer, the best way to fix this should probably return a reference instead:
const Hand& Player::getHand() const {
return hand;
}
I made this a const because returning a non-const could (potentially) allow you to break constness of a constant Player object. That is just inviting potential bugs.
Because of this, you may want to add a non-const version too:
Hand& Player::getHand() {
return hand;
}
Now you can't modify a const Player object, yet modify it properly when you need to.

QString and QByteArray memory usage

The QByteArray documentation states that it is to be used when memory conservation is critical. I've been working on a class (FieldName) that keeps an internal store of commonly used QString's so that when two FieldName objects are compared for equality, a quick integer comparison is done.
My thinking was that I could save some memory and gain speed by using QByteArray instead of QString since I only need standard ASCII characters. But when I change out the QString in the following code for QByteArray, my tests show that speed is increased, but memory usage more than doubles. This runs counter to the documentation.
#ifndef H_FIELDNAME
#define H_FIELDNAME
#include <QString>
class FieldName
{
public:
FieldName() : mKey(0) { init(); }
FieldName(const QString& s);
const QString& constString() const;
bool operator==(const FieldName& other) const { return mKey == other.mKey; }
bool operator!=(const FieldName& other) const { return mKey != other.mKey; }
private:
int mKey;
void init();
int findKey(const QString& s);
};
#endif
CPP file:
#include "fieldname.h"
// #include <QMutex> // demo version not thread-safe
#include <QVector>
static QVector<QString*> FieldName__List;
static bool FieldName__FirstCall(true);
FieldName::FieldName(const QString& s)
{
init();
mKey = findKey(s);
}
const QString& FieldName::constString() const
{
return(*FieldName__List.at(mKey));
}
void FieldName::init()
{
if(FieldName__FirstCall)
{
if(FieldName__List.isEmpty())
{
FieldName__List.append(new QString(""));
FieldName__FirstCall = false;
}
}
}
int FieldName::findKey(const QString& s)
{
if(s.isEmpty())
return 0;
int sz(FieldName__List.size());
for(int idx=1; idx<sz; ++idx)
{
if(s == *FieldName_List.at(idx))
return idx;
}
FieldName__List.append(new QString(s));
return(FieldName__List.size() - 1);
}
Can anyone let me know what I may be doing that is causing this to use more memory when I substitute QByteArray for QString in the above class?
Testcode:
QStringList qsl; // filled with 84000 unique English words
FieldName fn;
foreach(QString s, qsl)
{
fn = FieldName(s);
// do stuff here
}

0xC0000005: Access violation writing location 0xCCCCCCCC caused by trying to make safe empty chars

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.