-
Base class undefined
I keep getting this error when I try to create a new class called ReverseString that is derived from the base class String. The error is:
error C2504: 'String' : base class undefined
I have to create this class so there is no way around it. I can't make a function in string that does what ReverseString is supposed to do. I have to figure out why this error message is occurring. Any help is greatly appreciated. I will post my header and source code for Reverse String and then in the following post I will add my string.h and string.cpp. Thanks.
Code:
//reverse.h
#ifndef ReverseString_H
#define ReverseString_H
#include <iostream>
#include "string.h"
#include "strdrv.h"
using namespace std;
class ReverseString: public String
{
public:
ReverseString();
ReverseString(const ReverseString &rhs);
ReverseString(const char *str);
ReverseString operator=(const ReverseString &rhs);
ReverseString operator~();
};
#endif
// reverse.cpp
#define _CRT_SECURE_NO_DEPRECATE 1
#include <iostream>
#include <assert.h>
#include "reverse.h"
using namespace std;
ReverseString::ReverseString()
{
name = NULL;
stringlength = 0;
size = stringlength + 1;
buf = new char [size];
memset(buf, 0 , size);
assert(buf != 0);
buf[0] = '\0';
}
ReverseString::ReverseString(const ReverseString &rhs)
{
name = NULL;
stringlength = rhs.stringlength;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0, size);
assert(buf != 0);
for(int i = 0; i <= stringlength; i++)
buf[i] = rhs.buf[i];
}
ReverseString::ReverseString(const char *str)
{
name = NULL;
assert(str != 0);
stringlength = strlen(str);
size = stringlength + 1;
buf = new char[size];
memset(buf, 0 , size);
strcpy(buf, str);
}
ReverseString ReverseString::operator =(const ReverseString &rhs)
{
if(this != &rhs)
{
delete []buf;
stringlength = rhs.stringlength;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0, size);
strcpy(buf, rhs.buf);
}
return *this;
}
ReverseString ReverseString::operator ~()
{
int k = 0;
for(int i = stringlength; i>=0; i--)
{
buf[i]= buf[k];
k++;
}
return buf;
}
Also here is the header for the driver program:
Code:
// strdrv.h
#ifndef _STRDRV_H
#define _STRDRV_H
#include "string.h"
#include "reverse.h"
int main();
void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void test7();
void test8();
void test9();
void test10();
void test11();
void test12();
void test13();
void test14();
void test15();
void test16();
void test17();
void test18();
void test19();
void test20();
void wait();
#endif
-
Here is the string header and source code:
Code:
//string.h
#ifndef String_H
#define String_H
#include <iostream>
#include "strdrv.h"
using namespace std;
class String
{
friend String operator+(const String& lhs, const String& rhs);
friend String operator+(const String& rhs, const char* str);
friend String operator+(const char* str, const String& rhs);
friend String operator+(const String& rhs, char str);
friend String operator+(char str, const String& rhs);
friend int operator==(const String& lhs, const String& rhs);
friend int operator!=(const String& lhs, const String& rhs);
friend int operator< (const String& lhs, const String& rhs);
friend int operator<=(const String& lhs, const String& rhs);
friend int operator> (const String& lhs, const String& rhs);
friend int operator>=(const String& lhs, const String& rhs);
friend char* operator+(const String &rhs, int element);
friend char* operator+(int element, const String &rhs);
friend ostream& operator<<(ostream&, const String&);
public:
String();
String(const char* str);
String(char nme);
String(int sizeofstring);
String(const String &rhs);
String(char letter, int repeat);
~String();
void setName(const char* aname);
String& operator= (const String &rhs);
String& operator= (const char *st);
String& operator= (const char st);
String& operator+=(const String & str);
String operator+() const;
char& operator[](int i);
char& operator[](int i) const;
String& operator++();
String& operator--();
String operator++(int x);
String operator--(int x);
int getLength()const;
String substr(int start, int length);
const char* c_str() const;
void print();
protected:
int stringlength;
int size;
char * name;
char *buf;
};
#endif
// string.cpp
#define _CRT_SECURE_NO_DEPRECATE 1
#pragma warning(disable: 4996)
#pragma warning(disable: 4267)
#include <iostream>
#include <cctype>
#include <algorithm>
#include <assert.h>
#include "string.h"
using namespace std;
String::String()
{
name = NULL;
stringlength = 0;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0, size);
}
String::String(const char *str)
{
name = NULL;
assert( str != 0);
stringlength = strlen(str);
size = stringlength + 1;
buf = new char[size];
strcpy(buf, str);
}
String::String(char nme)
{
name = NULL;
stringlength = 1;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0, size);
buf[0] = nme;
}
String::String(int sizeofstring)
{
name = NULL;
assert(sizeofstring >= 0);
stringlength = sizeofstring;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0, size);
}
String::String(char letter, int repeat) : name(0), stringlength(repeat)
{
buf = new char[repeat+1];
memset( buf, 0, repeat + 1);
for(int i= 0; i< repeat; i++)
buf[i] = letter;
}
String::String(const String &rhs)
{
name = NULL;
stringlength = rhs.stringlength;
size = stringlength + 1;
buf = new char[size];
strcpy(buf, rhs.buf);
}
String::~String()
{
name = NULL;
delete []buf;
}
void String::setName(const char* aname)
{
name = NULL;
name = new char[strlen(aname + 1)];
strcpy(name, aname);
}
String& String::operator =(const String &rhs)
{
if(this != &rhs)
{
delete []buf;
stringlength = rhs.stringlength;
size = stringlength + 1;
buf = new char[size];
strcpy(buf, rhs.buf);
}
return *this;
}
String& String::operator =(const char *st)
{
String temp(st);
return operator =(temp);
}
String& String::operator =(char st)
{
stringlength = 1;
size = stringlength + 1;
buf = new char[size];
memset(buf, 0 , size);
buf[0] = st;
return *this;
}
char& String::operator [](int i) const
{
static char sink = '\0';
if(i < 0 || i> stringlength)
{
cout<< "Error with element" << endl;
sink = '\0';
return sink;
}
else
return buf[i];
}
char& String::operator [](int i)
{
static char sink = '\0';
if(i < 0 || i>stringlength)
{
cout<< "Error with element" << endl;
sink = '\0';
return sink;
}
else
return buf[i];
}
char* operator +(const String &rhs , int element)
{
static char* blank = '\0';
if(element < 0 || element > rhs.getLength())
return blank;
else
{
char *buf = new char[rhs.getLength() + 1];
strcpy(buf, rhs.buf);
return &buf[element];
}
}
char* operator +(int element, const String &rhs)
{
static char* blank = '\0';
if(element < 0 || element > rhs.getLength())
return blank;
else
{
char *buf = new char[rhs.getLength() + 1];
strcpy(buf, rhs.buf);
return &buf[element];
}
}
String& String::operator +=(const String & str)
{
int newsize = getLength() + str.getLength();
stringlength = newsize;
size = stringlength + 1;
char *temp = new char[size];
memset(temp, 0, size);
strcpy(temp, buf);
strcat(temp, str.buf);
delete []buf;
buf = temp;
return *this;
}
int String::getLength()const
{
return stringlength;
}
String operator +(const String& lhs, const String& rhs)
{
String result(lhs);
result += rhs;
return result;
}
String operator +(char str, const String& rhs)
{
String result(str);
result += rhs;
return result;
}
String operator +(const String& rhs, char str)
{
String result(rhs);
result += str;
return result;
}
String operator +(const char* str, const String& rhs)
{
String result(str);
result += rhs;
return result;
}
String operator +(const String& rhs, const char* str)
{
String result(rhs);
result += str;
return result;
}
String String::substr(int start, int length)
{
if(start <= 0 && start > stringlength)
cout<< "Start of substring not in string bounds" << endl;
else
{
if(length <= 0)
cout<< "Error: length of substring is negative" << endl;
else
{
if((start + length) > stringlength)
length = stringlength - start;
else
{
char* stringArray = new char[length + 1];
memset(stringArray, 0, length +1);
int i;
for(i = start; i < (start + length) ; i++)
stringArray[i-start] = (*this)[i];
stringArray[i - start] = '\0';
String temp(stringArray);
delete []stringArray;
return temp;
}
}
}
}
int operator==(const String& lhs, const String& rhs)
{
return strcmp(lhs.buf, rhs.buf)==0;
}
int operator!= (const String& lhs, const String& rhs)
{
return !(lhs.buf == rhs.buf);
}
int operator< (const String& lhs, const String& rhs)
{
return strcmp(lhs.buf, rhs.buf) <0;
}
int operator<= (const String& lhs, const String&rhs)
{
return strcmp(lhs.buf, rhs.buf) <=0;
}
int operator> (const String& lhs, const String& rhs)
{
return strcmp(lhs.buf, rhs.buf) >0;
}
int operator>= (const String& lhs, const String& rhs)
{
return strcmp(lhs.buf, rhs.buf) >=0;
}
ostream& operator<< (ostream& output, const String& stringoutput)
{
output<< stringoutput.buf;
return output;
}
String& String::operator ++()
{
for(int i = 0; i<stringlength; i++)
++buf[i];
return *this;
}
String String::operator +() const
{
char *temp = new char[stringlength + 1];
strcpy(temp, buf);
std::transform(temp, temp+stringlength, temp, toupper );
return temp;
}
String String::operator ++(int x)
{
String temp = *this;
++*this;
return temp;
}
String& String::operator --()
{
for(int i = 0; i<stringlength; i++)
--buf[i];
return *this;
}
String String::operator --(int x)
{
String temp = *this;
--*this;
return temp;
}
const char* String::c_str() const
{
return buf;
}
void String::print()
{
printf("%s: %s(%d)\n", name, buf, stringlength);
}
-
I think the ReverseString class needs to know more about String than it is derived from it.
Other than that, if I may say so, you seem to be going in the wrong direction (may-be because you have a very strange assignment). You already have a lot of operator overloads that are not intuitive and should be normal functions.
What the reverse string has different is that it has one more unintuitive operator (~), but otherwise it is a pretty ordinary string. Therefore I don't see why you would even inherit it. Why can't String just implement it?
-
Try renaming string.h to a different filename (and also update the #includes that reference it). I guess it is possible that it is conflicting with the standard string.h header.
Otherwise, I don't see why you would get that error. Is that the only compile error you get?
Edit: Actually a more likely problem is the circular include you have. There's no reason to #include "string.h" and "reverse.h" inside strdrv.h.
-
Are all of your files located in the same directory, and are you sure that is the working directory from which you are compiling?
string.h is a standard library header, so you could possibly be picking up the wrong header with your #include directive.
-
As soon as I take reverse.h out of strdrv.h then it hits me with these errors:
error LNK2019: unresolved external symbol "void __cdecl test19(void)" (?test19@@YAXXZ) referenced in function _main
fatal error LNK1120: 1 unresolved externals
-
Here is the body of the driver:
Code:
// strdrv.cpp
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "strdrv.h"
using namespace std;
ofstream csis;
int main() {
csis.open("csis.dat");
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();
test12();
test13();
test14();
test15();
test16();
test17();
test18();
test19();
csis.close();
}
void test1() {
system("cls");
cout << "1. Testing: String default ctor." << endl << endl;
csis << "1. Testing: String default ctor." << endl << endl;
String s1;
s1.setName("s1");
s1.print();
wait();
}
void test2() {
system("cls");
cout << "2. Testing: String one arg (char *) ctor." << endl << endl;
csis << "2. Testing: String one arg (char *) ctor." << endl << endl;
String s2("ABC");
s2.setName("s2");
s2.print();
wait();
}
void test3() {
system("cls");
cout << "3. Testing: String one arg (char) ctor." << endl << endl;
csis << "3. Testing: String one arg (char) ctor." << endl << endl;
String s3('Z');
s3.setName("s3");
s3.print();
wait();
}
void test4() {
system("cls");
cout << "4. Testing: String one arg (int) ctor." << endl << endl;
csis << "4. Testing: String one arg (int) ctor." << endl << endl;
String s4(10);
s4.setName("s4");
s4.print();
wait();
}
void test5() {
system("cls");
cout << "5. Testing: String copy ctor." << endl << endl;
csis << "5. Testing: String copy ctor." << endl << endl;
String s5("Haley Laurel");
s5.setName("s5");
s5.print();
String t5(s5);
t5.setName("t5");
t5.print();
wait();
}
void test6() {
system("cls");
cout << "6. Testing: String two arg (char, int) ctor." << endl << endl;
csis << "6. Testing: String two arg (char, int) ctor." << endl << endl;
String s6('*', 10);
s6.setName("s6");
s6.print();
wait();
}
void test7() {
system("cls");
cout << "7. Testing: String assignment." << endl << endl;
csis << "7. Testing: String assignment." << endl << endl;
String s7("Samantha Morgan"), t7, u7;
s7.setName("s7");
t7.setName("t7");
u7.setName("u7");
t7 = u7 = s7;
s7.print();
t7.print();
u7.print();
wait();
}
void test8() {
system("cls");
cout << "8. Testing: String assignment." << endl << endl;
csis << "8. Testing: String assignment." << endl << endl;
String s8("ABC");
s8.setName("s8");
s8 = s8;
s8.print();
wait();
}
void test9() {
system("cls");
cout << "9. Testing: Implicit type conversion." << endl << endl;
csis << "9. Testing: Implicit type conversion." << endl << endl;
String s9;
s9 = "ABC";
s9.setName("s9");
s9.print();
wait();
}
void test10() {
system("cls");
cout << "10. Testing: String concatenation." << endl << endl;
csis << "10. Testing: String concatenation." << endl << endl;
String s10("DEF");
String t10('H');
String u10("ABC" + s10 + "G" + t10 + 'I');
u10.setName("u10");
u10.print();
String v10('X' + u10);
v10.setName("v10");
v10.print();
wait();
}
void test11() {
system("cls");
cout << "11. Testing: String concatenation." << endl << endl;
csis << "11. Testing: String concatenation." << endl << endl;
String s11('A');
String t11("BC");
s11.setName("s11");
t11.setName("t11");
s11 += s11 += t11 += 'D';
s11.print();
t11.print();
wait();
}
void test12() {
system("cls");
cout << "12. Testing: String unary operator." << endl << endl;
csis << "12. Testing: String unary operator." << endl << endl;
String s12("Unary +");
String t12(+s12);
s12.setName("s12");
t12.setName("t12");
s12.print();
t12.print();
s12 = +s12;
s12.print();
wait();
}
void test13() {
system("cls");
cout << "13. Testing: String comparison operators." << endl << endl;
csis << "13. Testing: String comparison operators." << endl << endl;
String s13("ABC"), t13("ABCD");
s13.setName("s13");
t13.setName("t13");
s13.print();
t13.print();
cout << endl;
cout << "== " << (s13 == t13 ? "True" : "False") << endl;
cout << "!= " << (s13 != t13 ? "True" : "False") << endl;
cout << "< " << (s13 < t13 ? "True" : "False") << endl;
cout << "<= " << (s13 <= t13 ? "True" : "False") << endl;
cout << "> " << (s13 > t13 ? "True" : "False") << endl;
cout << ">= " << (s13 >= t13 ? "True" : "False") << endl;
csis << endl;
csis << "== " << (s13 == t13 ? "True" : "False") << endl;
csis << "!= " << (s13 != t13 ? "True" : "False") << endl;
csis << "< " << (s13 < t13 ? "True" : "False") << endl;
csis << "<= " << (s13 <= t13 ? "True" : "False") << endl;
csis << "> " << (s13 > t13 ? "True" : "False") << endl;
csis << ">= " << (s13 >= t13 ? "True" : "False") << endl;
wait();
}
void test14() {
system("cls");
cout << "14. Testing: Overloaded subscript operator." << endl << endl;
csis << "14. Testing: Overloaded subscript operator." << endl << endl;
String s14("C++ is fun.");
s14.setName("s14");
for (int i = -1; i <= s14.getLength(); i++) {
char& ch = s14[i];
if (ch != '\0')
++ch;
}
s14.print();
wait();
}
void test15() {
system("cls");
cout << "15. Testing: Pointer notation." << endl << endl;
csis << "15. Testing: Pointer notation." << endl << endl;
String s15("ABCDE");
s15.setName("s15");
for(int i = 0; i < s15.getLength(); i++)
++(*(s15+i));
for (int j = 0; j < s15.getLength(); j++) {
cout << *(j + s15);
csis << *(j + s15);
}
cout << endl;
csis << endl;
wait();
}
void test16() {
system("cls");
cout << "16. Testing: Increment and decrement operators." << endl << endl;
csis << "16. Testing: Increment and decrement operators." << endl << endl;
String s16("ABC");
String t16(++s16);
s16.setName("s16");
t16.setName("t16");
s16.print();
t16.print();
String u16("ABC");
String v16(u16++);
u16.setName("u16");
v16.setName("v16");
u16.print();
v16.print();
String w16("ABC");
String x16(--w16);
w16.setName("w16");
x16.setName("x16");
w16.print();
x16.print();
String y16("ABC");
String z16(y16--);
y16.setName("y16");
z16.setName("z16");
y16.print();
z16.print();
wait();
}
void test17() {
system("cls");
cout << "17. Testing: Substr function." << endl << endl;
csis << "17. Testing: Substr function." << endl << endl;
String s17("Jai Guru Dev"), t17;
s17.setName("s17");
t17.setName("t17");
t17 = s17.substr(4, 8);
s17.print();
t17.print();
wait();
}
void test18() {
system("cls");
cout << "18. Testing: Output function." << endl << endl;
csis << "18. Testing: Output function." << endl << endl;
String s18("Haley");
String t18("Laurel");
String u18("Stegman");
cout << s18 << t18 << u18;
cout << endl;
csis << endl;
wait();
}
void wait() {
char buf;
cout << endl << "Press any key to continue." << endl;
csis << endl << endl;
cin.get(buf);
}
-
This should mean that you either don't have or fail to compile the implementation of test19.
-
I forgot to put test 19 in the driver. Sorry everybody