I am in the process of constructing a StackArray. I already have a "Stack.h" implemented with a constructor. I was wondering what I would do in my "StackArray.h" file to use the Stack.h file. I was thinking to use inheritance but it was giving me a error.
My code is as follows:
Array.h
#include <iostream>
#include <assert.h>
using namespace std;
#ifndef _ARRAY_H
#define _ARRAY_H
template<class T>
class Array{
private:
T *a;
int length;
public:
// constructor
Array (int len){
length = len;
a = new T[length];
for (int i = 0; i < len; i++){
a[i]=0;
}
}
// destructor
~Array()
{delete[] a;}
// operator overload
T& operator [](int i){
assert (i>=0 && i < length);
return a[i];
}
//get the length of the array
int arraylength(){
return length;
}
};
#endif
ArrayStack.h
#ifndef _ARRAYSTACK_H_
#define _ARRAYSTACK_H_
#include "Array.h"
using namespace std;
template<class T>
class ArrayStack
{
protected:
Array<T> a;
int n;
public:
ArrayStack(int len);
virtual ~ArrayStack();
};
template<class T>
ArrayStack<T>::ArrayStack(int len){
// I don't know what to do here to implemented constructor from another class.
}
#endif
Any suggestion would be great, Thank you
Andy
Related
When I try to run an instance of the matrix class I'm writing, I get the following error.
main.cpp|6|error: expected primary-expression before 'double'|
I believe there's something wrong with the constructor but i can't figure what.
How can I fix my code? Below what I've written so far.
matrix.h
#ifndef MATRIX_H
#define MATRIX_H
template<class T>
class matrix{
public:
matrix(int n, int m);
~matrix();
void fillM(T n);
void print() const;
private:
T** body_;
int lin_;
int col_;
void eraseMatrix();
};
#endif
matrix.cpp
#include "matrix.h"
#include <iostream>
template<class T>
matrix<T>::matrix(int n, int m):col_(m),lin_(n),body_(new T*[n]){
for(int i=0;i<n;i++){
body_[i] = new T[m];
}
}
template<class T>
matrix<T>::~matrix<T>(){
eraseMatrix();
}
template<class T>
void matrix<T>::eraseMatrix(){
for(int i=0;i<lin_;i++){
delete [] body_[i];
}
delete [] body_;
return;
}
template<class T>
void matrix<T>::fillM(T n){
int j;
for(int i = 0;i<lin_;i++){
for(j = 0;j<col_;j++){
body_[i][j] = n;
}
}
return;
}
template<class T>
void matrix<T>::print() const{
int j;
for(int i=0;i<lin_;i++){
for(j=0;j<col_;j++){
std::cout<<body_[i][j]<<" ";
}
std::cout<<std::endl;
}
}
main.cpp
#include <iostream>
#include "matrix.h"
using namespace std;
int main(){
matrix<double>::matrix<double> A(5,5);//error happens here
A.fillM(5.2);
A.print();
return 0;
}
}
You don't need to write matrix<double>::matrix<double> to construct an instance. Just matrix<double> A(5,5);.
My question is that, I have a template class template<class T> AList as base, and I wanna get a derived class from the template, i.e. get class BList: public AList<mydefinedtype> without much modification.
alist.h
#ifndef alist_h
#define alist_h
template<class T> class AList
{
public:
AList(){
arr = new T[20];
numitems = 0;
};
void append(T value);
private:
T *arr;
int numitems;
};
#endif /* alist_h */
alist.cpp
#include "alist.h"
template<class T> void AList<T>::append(T value)
{
arr[numitems] = value;
++numitems;
return;
}
blist.h
#include "alist.cpp"
#include <string>
using namespace std;
typedef struct
{
string a, b;
int key;
} record;
class BList: public AList<record>{
public:
void test(void){
cout << "this is from BList" << endl;
}
};
blist.cpp
#include "blist.h"
main.cpp
#include <iostream>
#include "blist.cpp"
using namespace std;
int main(){
record testRecord[3];
testRecord[0] = {"Mark", "A", 1};
testRecord[1] = {"Anla", "B", 2};
testRecord[2] = {"Cindy", "C", 3};
BList blist = BList();
for(auto i: testRecord){
// blist.append(i); // will compile error
blist.test();
}
return 0;
}
It will fail as follows, I wonder how to compile or how to fix the bug.
error info
Undefined symbols for architecture x86_64:
"AList<record>::append(s)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
Not sure where comes from the issue.
// Example program
#include <iostream>
#include <string>
struct record{
int a;
};
template<class T>
class AList{
public:
AList()=default;
void append(T value){}
};
template<class T>
class BList:public AList<T>{
public:
void test(void){}
};
int main()
{
BList<record> blist;
record recordarr[3] ;
// some initialization
for(auto i:recordarr){
blist.append(i);
blist.test();
}
}
The problem you have is that the AList() constructor, append(T) and test() are only declared but not defined. The above code should compile.
You should put your template classes entirely in header files. See this question and this C++ FAQ for details on why.
You should also never #include .cpp files. You should only ever #include header files.
Below I have your code after the required modifications to make it compile. I also removed your memory leak.
alist.h:
#ifndef alist_h
#define alist_h
template<class T> class AList {
public:
AList() {
arr = new T[20];
numitems = 0;
};
~AList() {
delete[] arr;
}
void append(T value) {
arr[numitems] = value;
++numitems;
}
private:
T *arr;
int numitems;
};
#endif /* alist_h */
blist.h:
#ifndef blist_h
#define blist_h
#include "alist.h"
#include <string>
using namespace std;
typedef struct {
string a, b;
int key;
} record;
class BList: public AList<record> {
public:
void test(void) {
cout << "this is from BList" << endl;
}
};
#endif /* blist_h */
main.cpp:
#include <iostream>
#include "blist.h"
using namespace std;
int main() {
record testRecord[3];
testRecord[0] = {"Mark", "A", 1};
testRecord[1] = {"Anla", "B", 2};
testRecord[2] = {"Cindy", "C", 3};
BList blist = BList();
for (auto i: testRecord) {
blist.append(i);
blist.test();
}
return 0;
}
Summary of changes
I made the following changes:
Moved body of AList::append into alist.h, and deleted alist.cpp
Added AList destructor to free the dynamically allocated memory allocated in AList::AList
In blist.h, included alist.h instead of alist.cpp
Deleted blist.cpp
In main.cpp, included blist.h instead of blist.cpp
I am half way into my course.I am unable to understand the logic behind the errors I am receiving. I have already tried to counter it by using appropriate directives at the bottom of my Array.h file. I am receive the following 2 errors across all functions:
note: 'const T& udbhavAg::Container::Array::operator const' previously declared here
const T &Array::operator[](int index) const {
error: redefinition of 'const T& udbhavAg::Container::Array::operator const'
const T &Array::operator[](int index) const {
My questions are the following :
Why are the files being declared twice?
Why are they being redefined?
Main.cpp
#include <iostream>
#include "Point.h"
#include "Line.h"
#include "Circle.h"
#include "Array.h"
#include "ArrayException.h"
using namespace std;
using namespace udbhavAg::CAD;
using namespace udbhavAg::Container;
using namespace udbhavAg;
int main()
{
Array<Point> points(10);
return 0;
}
Array.h
#include "Point.h"
#include <cstring>
#include "ArrayException.h"
#ifndef ARRAY_H
#define ARRAY_H
//#include "Array.cpp"
namespace udbhavAg
{
namespace Container
{
template <typename T>
class Array {
private:
T *m_data;
int m_size;
public:
Array();
Array(int size);
Array(const Array &obj);
virtual ~Array();
//const Array operator= ( const Array & source);
Array<T> &operator=(const Array &source);
int Size() const;
void setElement(int index, T p);
T &getElement(int index) const;
T &operator[](int index);
const T &operator[](int index) const;
};
}
}
#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif
#endif ARRAY_H
Array.cpp
#include "Array.h"
#include "ArrayException.h"
namespace udbhavAg
{
namespace Container
{
template<typename T>
Array<T>::Array():m_size(3),m_data(new T[m_size]) {}
template<typename T>
Array<T>::Array(int size): m_size(size), m_data(new T[m_size]) {}
template<typename T>
Array<T>::~Array()
{
delete[] m_data;
cout << "Destructor called" << endl;
}
template<typename T>
Array<T>::Array(const Array &obj) {
m_size = obj.m_size;
m_data = new CAD::Point[m_size];
for (int i = 0; i < m_size; i++)
{
m_data[i] = obj.operator[](i);
}
}
template<typename T>
int Array<T>::Size() const
{
return m_size;
}
template<typename T>
T &Array<T>::getElement(int index) const
{
try
{
if (index >= m_size || index < 0)
{
throw (OutofBoundsException(index));
}
else
{
return m_data[index];
}
}
catch (ArrayException &error)
{
cout << error.GetMessage();
}
}
template<typename T>
void Array<T>::setElement(int index, T p)
{
try
{
if (index >= m_size || index < 0)
{
// OutofBoundsException error = OutofBoundsException(index);
// ArrayException& abc = error;
throw (OutofBoundsException(index));
}
else
{
m_data[index] = p;
}
}
catch (ArrayException &error)
{
cout << error.GetMessage();
}
}
template<typename T>
Array<T> & Array<T>::operator=(const Array &source)
{
if(&source != this){ //edited self assignment test
if(m_size != source.m_size){//diff sized arrays
delete [] m_data; //reclaim space
m_size = source.m_size;
m_data = new CAD::Point[m_size]; //space created
}
}
for(int i=0; i<m_size; i++){
m_data[ i ] = source.m_data[i];}
return *this; //enables cascading a=b=c
}
template<typename T>
T &Array<T>::operator[](int index) {
try
{
if (index >= m_size || index < 0)
{
// OutofBoundsException error = OutofBoundsException(index);
// ArrayException& abc = error;
throw (OutofBoundsException(index));
}
else
{
return m_data[index];
}
}
catch (ArrayException &error)
{
cout << error.GetMessage();
}
}
template<typename T>
const T &Array<T>::operator[](int index) const {
try
{
if (index >= m_size || index < 0)
{
// OutofBoundsException error = OutofBoundsException(index);
// ArrayException& abc = error;
throw (OutofBoundsException(index));
}
else
{
return m_data[index];
}
}
catch (ArrayException &error)
{
cout << error.GetMessage();
}
}
}
}
probably because in Array.h :
#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif
so Array.cpp #include Array.h whose #include Array.cpp because Array_cpp is not defined
Do not include source file in your header files
Out of that why in Array.h
#ifndef ARRAY_H
#define ARRAY_H
is not at the beginning of the file ?
So possible exclusive solutions to solve are :
to remove #include "Array.h" at the beginning of Array.cpp
to add #define Array_cpp to be the very first line in Array.cpp
in both case you must not compile Array.cpp in your Makefile or equivalent nor link with it.
But the best one is to replace in Array.h
#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif
by the definitions from the file Array.cpp and to delete the file Array.cpp.
The template classes are special, all template methods must be defined in the header file and only in it, not in a source file also compiled as a 'normal' source file, the compiler does the stuff for you
I made a class with a header and a cpp and a main class. When doing so all is good! When separating a class that I will have 2 classes (header+cpp) and one main Class A (Board) does not recognize class B (IllegalCoordinateException) even though I inserted the include. This is probably a newbies question and I might lose some points, but I am stuck in finding my problem.
Here is my working code(stripped down to only the important parts):
main.cpp
#include "Board.h"
#include <iostream>
using namespace std;
int main() {
Board board1{4}; // Initializes a 4x4 board
try {
board1[{3,4}]='O'; // This should raise an exception
} catch (const IllegalCoordinateException& ex) {
cout << "Illegal coordinate" << ex.theCoordinate() << endl; // prints "Illegal coordinate: 3,4"
}
return 0;
}
Board.h
#ifndef CIRC_H
#define CIRC_H
#include <iostream>
#include <string>
using namespace std;
struct coord {
int x;
int y;
};
class IllegalCoordinateException{
coord _coord;
public:
IllegalCoordinateException(coord c){
_coord = c;
}
string theCoordinate() const{
return to_string(_coord.x)+","+to_string(_coord.y);
}
};
class xo{
char x;
public:
char getChar() const{return x;}
char& operator= (const char c){x = c;}
xo& operator= (const xo _xo){
x = _xo.getChar();
return *this;
}
void clear(){
x = '.';
}
operator char() const{
return x;
}
};
class Board{
private:
coord _coord;
xo** board;
int size;
public:
Board();
Board(int v);
~Board();
xo& operator[](coord c); // here is where I use "IllegalCoordinateException"
};
#endif
Board.cpp
#include <iostream>
#include <vector>
#include "Board.h"
using namespace std;
void freeBoard(xo** board,int size){
for(int i = 0 ; i < size ; i++){
delete[] board[i];
}
}
Board::Board()
{
size = 0;
board = new xo* [size];
}
Board::Board(int v)
{
size = v;
board = new xo* [size];
for (int i=0; i<size; i++)
{
board[i] = new xo[size];
for(int j = 0 ; j < size ; j++){
board[i][j].clear();
}
}
}
Board::~Board(){
freeBoard(board,size);
delete[] board;
}
xo& Board::operator[](coord c)
{
if(c.x < size && c.y < size)
{
return board[c.x][c.y];
}
else
{
throw IllegalCoordinateException(c);
}
}
After seperation:
main.cpp
No diff
Board.h also cpp no diff
#ifndef CIRC_H
#define CIRC_H
#include "IllegalCoordinateException.h"
#include <iostream>
#include <string>
using namespace std;
struct coord {
int x;
int y;
};
class xo{
char x;
public:
char getChar() const{return x;}
char& operator= (const char c){x = c;}
xo& operator= (const xo _xo){
x = _xo.getChar();
return *this;
}
void clear(){
x = '.';
}
operator char() const{
return x;
}
};
class Board{
private:
coord _coord;
xo** board;
int size;
public:
Board();
Board(int v);
~Board();
xo& operator[](coord c);
};
#endif
IllegalCoordinateException.h // I also seperated in my code to .h and .cpp (but ofcourse there is no real diff.
#ifndef CIRC_H
#define CIRC_H
#include <iostream>
#include "Board.h"
using namespace std;
class IllegalCoordinateException{
coord _coord;
public:
IllegalCoordinateException(coord c){ _coord = c;}
string theCoordinate() const{return to_string(_coord.x)+","+to_string(_coord.y);}
};
#endif
When doing
$ g++ -g -Og -std=c++0x main.cpp Board.cpp IllegalCoordinateException.cpp
I get:
Board.cpp: In member function ‘xo& Board::operator’:
Board.cpp:60:43: error: ‘IllegalCoordinateException’ was not declared
in this scope
throw IllegalCoordinateException(c);
How can this be? I mean I am including it in the Board.h so Board.cpp is supposed to recognize it!? I tried also to include it in Board.cpp and also make a forward declaration in Board.cpp but both were frugal.
Both of your header files have #ifndef CIRC_H / #define CIRC_H.
So when the first one is included (no matter which order), it defines CIRC_H, and when the second one is included, it gets ignored because the whole file is within #ifndef CIRC_H.
Solution: use a different macro name for each header file.
I am creating CPP application that can create List's: string arrays. When initialization is called it get's variadic parameters and should insert them into a string array. It gives Segmentation error. Also if I remove Students_Second_Group.push(), everything works fine. Any suggestions?
// Main.cpp
#include "List.h"
int main() {
List Students_First_Group(4), Students_Second_Group(3);
Students_First_Group.push("Jonas Jonaits", "Tomas Tomaitis", "Petras Petraitis", "Donatas Petkevicius");
Students_Second_Group.push("Mantas Jonaitis", "Tautvydas Tomaitis", "Linas Linaitis");
return 0;
}
// List.h
#ifndef _LIST_H_
#define _LIST_H_
#include <iostream>
#include <string>
#include <vector>
#include <cstdarg>
using namespace std;
class List {
private:
size_t size;
vector<string> arr;
public:
List(int size);
void push(const char* str...);
~List();
};
#endif
// List.cpp
#include "List.h"
List::List(int s) {
if(size > 0)
size = s;
else
size = 10;
arr = vector<string> (s);
}
void List::push(const char* str...) {
va_list arg;
va_start(arg, str);
while (str) {
arr.push_back(str);
str = va_arg(arg, const char *);
}
va_end(arg);
}
List::~List() {}
you can solve your issue with varadic template but
because they are template varadic template should be put in the header
for more info http://en.cppreference.com/w/cpp/language/parameter_pack
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class List {
private:
size_t size;
vector<string> arr;
void push() {}
public:
List(int size);
template<typename ... Rest>
void push(const char* first, Rest ... rest) {
arr.push_back(first);
push(rest...);
}
~List();
};
List::List(int s) {
if(size > 0)
size = s;
else
size = 10;
arr = vector<string> (s);
}
List::~List() {}
int main() {
List Students_First_Group(4), Students_Second_Group(3);
Students_First_Group.push("Jonas Jonaits", "Tomas Tomaitis", "Petras Petraitis", "Donatas Petkevicius");
Students_Second_Group.push("Mantas Jonaitis", "Tautvydas Tomaitis", "Linas Linaitis");
return 0;
}