inheritance problem

G

Gary Wessle

Hi

in the attempt below, I intend to use 2 derived classes whose objects
c'tor fires a base class method which build a string "main_menu" which
is a concatenation of the strings for each derived object c'tor
argument. ok, let me explain in a different language; but before, here
is the expected output

preform Thread task.
preform non-thread task.

why did not it happen?
thanks

// the code.

// task.h
#ifndef TASK_H
#define TASK_H
#include <string>
#include <vector>

class Task {
std::string main_menu;
public:
Task();
void mm_build(std::string);
void p_main_menu();
};

class Thr_task : public Task {
public:
Thr_task(std::string);
};


class No_thr_task : public Task {
public:
No_thr_task(std::string);
};

#endif


****************************************************************
//task.cpp
#include <sstream>
using std::stringstream;
#include <fstream>
using std::ifstream;
#include <iostream>
using namespace std;

#include "task.h"

/* the base class */
Task::Task(){
p_main_menu();
}

void Task::p_main_menu(){
cout << main_menu << endl;
}

void Task::mm_build(string s){
main_menu + ".\n" + s;
}


/* the drived class 1 */
Thr_task::Thr_task(string n)
{
Task::mm_build(n);
}

/* the drived class 2 */
No_thr_task::No_thr_task(string n)
{
Task::mm_build(n);
}


****************************************************************
//main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Task dummy;
}
 
M

mlimber

Gary said:
Hi

in the attempt below, I intend to use 2 derived classes whose objects
c'tor fires a base class method which build a string "main_menu" which
is a concatenation of the strings for each derived object c'tor
argument. ok, let me explain in a different language; but before, here
is the expected output

preform Thread task.
preform non-thread task.

why did not it happen?
thanks

// the code.

// task.h
#ifndef TASK_H
#define TASK_H
#include <string>
#include <vector>

You don't use vector.
class Task {
std::string main_menu;
public:
Task();
void mm_build(std::string);

You should be passing all strings here by const reference. See:

http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.1
void p_main_menu();
};

class Thr_task : public Task {
public:
Thr_task(std::string);
};


class No_thr_task : public Task {
public:
No_thr_task(std::string);
};

#endif


****************************************************************
//task.cpp
#include <sstream>
using std::stringstream;
#include <fstream>
using std::ifstream;
#include <iostream>
using namespace std;

Why explicitly specify stringstream and ifstream when you also use the
whole std namespace, which brings both into scope anyway? Also, you
don't use either of those classes. Please post minimal code
(http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8) so as
not to confuse things.
#include "task.h"

Stylistically, I prefer to put all using statements after *all* headers
so that the headers don't have extra (and perhaps unexpected) symbols
in the global namespace.
/* the base class */
Task::Task(){
p_main_menu();
}

void Task::p_main_menu(){
cout << main_menu << endl;
}

void Task::mm_build(string s){
main_menu + ".\n" + s;
}


/* the drived class 1 */
Thr_task::Thr_task(string n)
{
Task::mm_build(n);
}

There's no need to qualify mm_build here. There's no other mm_build in
this scope. Anywho, here's what this constructor implicitly does:

Thr_task::Thr_task(string n)
: Task()
{
Task::mm_build(n);
}

The base class constructor has already been called before you build the
menu. Why not have the Task constructor accept a string, which it then
uses to build a menu and, if you must, print it? Better yet, have the
derived constructors or the user call the print function.
/* the drived class 2 */
No_thr_task::No_thr_task(string n)
{
Task::mm_build(n);
}


****************************************************************
//main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Task dummy;
}

Cheers! --M
 
G

Gary Wessle

another variation gave me more errors

****************************************************************
#ifndef TASK_H
#define TASK_H
#include <string>
#include <vector>

class Task {
static std::string main_menu;
public:
Task(std::string);
void p_main_menu();
};

class Thr_task : public Task {
public:
Thr_task(std::string);
};


class No_thr_task : public Task {
public:
No_thr_task(std::string);
};

#endif

****************************************************************

#include <sstream>
using std::stringstream;
#include <fstream>
using std::ifstream;
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;

using namespace std;

#include "task.h"

/* the base class */
Task::Task(string s)
{
main_menu = main_menu + ".\n" + s; //<<<<<<< line 18
}

void Task::p_main_menu(){
cout << main_menu << endl; //<<<<<<<<< line 22
}

/* the drived class 1 */
Thr_task::Thr_task(string n):
Task(n)
{
}

/* the drived class 2 */
No_thr_task::No_thr_task(string n):
Task(n)
{
}

****************************************************************

#include <iostream>
using std::cout;
using std::endl;
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Task dummy("");
}

****************************************************************

cd /home/fred/myProg/try/
make -k
g++ -gdwarf-2 -c -o task.o task.cpp
g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
task.o: In function `Task::p_main_menu()':
/home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
task.o: In function `Task':
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
collect2: ld returned 1 exit status
make: *** [proj] Error 1

Compilation exited abnormally with code 2 at Fri Nov 10 14:11:35
 
S

Salt_Peter

Gary said:
another variation gave me more errors

****************************************************************
#ifndef TASK_H
#define TASK_H
#include <string>
#include <vector>

class Task {
static std::string main_menu;

don't use static members until you understand the implications and how
to initialize them.
public:
Task(std::string);

Always pass by reference, by const reference.
Otherwise copies can get very expensive.
void p_main_menu();

Does that function modify the object: no
Make it const.
};

class Thr_task : public Task {
public:
Thr_task(std::string);

by const ref
};


class No_thr_task : public Task {
public:
No_thr_task(std::string);

by const ref
};

#endif

****************************************************************

#include <sstream>
using std::stringstream;
#include <fstream>
using std::ifstream;
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;

using namespace std;

#include "task.h"

/* the base class */
Task::Task(string s)
{
main_menu = main_menu + ".\n" + s; //<<<<<<< line 18
}

use the init list, see code below
void Task::p_main_menu(){
cout << main_menu << endl; //<<<<<<<<< line 22
}

/* the drived class 1 */
Thr_task::Thr_task(string n):
Task(n)
{
}

/* the drived class 2 */
No_thr_task::No_thr_task(string n):
Task(n)
{
}

****************************************************************

#include <iostream>
using std::cout;
using std::endl;
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Task dummy("");
}

****************************************************************

cd /home/fred/myProg/try/
make -k
g++ -gdwarf-2 -c -o task.o task.cpp
g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
task.o: In function `Task::p_main_menu()':
/home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
task.o: In function `Task':
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
collect2: ld returned 1 exit status
make: *** [proj] Error 1

Compilation exited abnormally with code 2 at Fri Nov 10 14:11:35

#include <iostream>
#include <string>

class Task {
std::string main_menu;
public:
Task(const std::string&);
void p_main_menu() const;
};

Task::Task(const std::string& s)
: main_menu(".\n" + s)
{
}

void Task::p_main_menu() const
{
std::cout << main_menu << std::endl;
}

class Thr_task : public Task {
public:
Thr_task(const std::string&);
};

Thr_task::Thr_task(const std::string& s)
: Task(s)
{
}

class No_thr_task : public Task {
public:
No_thr_task(const std::string&);
};

No_thr_task::No_thr_task(const std::string& s)
: Task(s)
{
}

int main()
{
Thr_task tt("preform Thread task");
tt.p_main_menu();

No_thr_task ntt("preform non-thread task");
ntt.p_main_menu();

Task dummy("dummy");
dummy.p_main_menu();
}

/*
..
preform Thread task
..
preform non-thread task
..
dummy
*/
 
G

Gary Wessle

mlimber said:
You don't use vector.


You should be passing all strings here by const reference. See:

http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.1


Why explicitly specify stringstream and ifstream when you also use the
whole std namespace, which brings both into scope anyway? Also, you
don't use either of those classes. Please post minimal code
(http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8) so as
not to confuse things.


Stylistically, I prefer to put all using statements after *all* headers
so that the headers don't have extra (and perhaps unexpected) symbols
in the global namespace.


There's no need to qualify mm_build here. There's no other mm_build in
this scope. Anywho, here's what this constructor implicitly does:

Thr_task::Thr_task(string n)
: Task()
{
Task::mm_build(n);
}

The base class constructor has already been called before you build the
menu. Why not have the Task constructor accept a string, which it then
uses to build a menu and, if you must, print it? Better yet, have the
derived constructors or the user call the print function.


Cheers! --M

I tried many ways to get this to work, the best I can do is as follows
but still getting the error

****************************************************************
cd /home/fred/myProg/try/
make -k
g++ -gdwarf-2 -c -o task.o task.cpp
g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
task.o: In function `Task::print_mm()':
/home/fred/myProg/try/task.cpp:19: undefined reference to `Task::main_menu'
task.o: In function `Task':
/home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
collect2: ld returned 1 exit status
make: *** [proj] Error 1

Compilation exited abnormally with code 2 at Fri Nov 10 17:23:05


//task.h
****************************************************************
#ifndef TASK_H
#define TASK_H
#include <string>

class Task {
static std::string main_menu;
public:
Task(std::string);
void print_mm();
};

class Thr_task : public Task {
public:
Thr_task(std::string);
void print_menu();
};


class No_thr_task : public Task {
public:
No_thr_task(std::string);
};

#endif

//task.cpp
****************************************************************
1 #include <iostream>
2 #include <string>
3 using std::cout;
4 using std::endl;
5 using std::string;
6
7 using namespace std;
8
9 #include "task.h"
10
11 /* the base class */
12 Task::Task(string s)
13 {
14 main_menu = main_menu + ".\n" + s;
15 }
16
17 void Task::print_mm(){
18
19 cout << main_menu << endl;
20 }
21
22 /* the drived class 1 */
23 Thr_task::Thr_task(const string n) :
24 Task(n)
25 {
26 }
27 void Thr_task::print_menu(){
28 print_mm();
29 }
30
31 /* the drived class 2 */
32 No_thr_task::No_thr_task(const string n) :
33 Task(n)
34 {
35 }

//main.cpp
****************************************************************
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Thr_task dummy(""); //only to print the main_menu
dummy.print_menu();
}
 
G

Gary Wessle

....

the idea I had in mind is to create objects of derived classes and
once I finish creating them, I then print the main_menu. not to print
the menu ever time I create an object. and that is why I thought to
use the static std::string main_menu.
once the menu prints it should show "as its items" the string passed
to the derived class c'tor.
 
G

Gary Wessle

here is the code after all the fixes plus trying to use a static
member to hold the menu items from previous derived class objects.
since my idea is to initialize different derived class objects and
then print a menu listing them in the order they were created. i.e
1. preform Thread task.
2. preform non-thread task.
3. preform whatever.

thus I need to create the objects from their correct type like this

Thr_task t1("preform Thread task.");
No_thr_task n1("preform non-thread task.");
Whatever_type w1("preform whatever task.");

and if possible with the least typing "with out printing each time I
create an object" but only when I signal printing the whole menu.
maybe like
base_class bc("");
bc.print_mm();
cout << "please make a selection from the menu: " << endl;

I read a bit and fount that I have to set a static member and a static
member function to work with it, note below.

//task.h
****************************************************************
#ifndef TASK_H
#define TASK_H
#include <string>

class Task {
static std::string main_menu;
public:
Task(const std::string&);
static void build_mm( const std::string& );
void print_mm() const;
};

class Thr_task : public Task {
public:
Thr_task(const std::string&);
void print_menu() const;
};


class No_thr_task : public Task {
public:
No_thr_task(const std::string&);
};

#endif





//task.cpp
****************************************************************
1 #include <iostream>
2 #include <string>
3 using std::cout;
4 using std::endl;
5 using std::string;
6
7 using namespace std;
8
9 #include "task.h"
10
11 /* the base class */
12 Task::Task(const string& s)
13 {
14 build_mm(s);
15 }
16
17 void Task::print_mm() const {
18 cout << main_menu << endl;
19 }
20
21 void Task::build_mm(const string& s){
22 main_menu = main_menu + ".\n" + s;
23 }
24
25 /* the drived class 1 */
26 Thr_task::Thr_task(const string& n) :
27 Task(n)
28 {
29 }
30 void Thr_task::print_menu() const {
31 print_mm();
32 }
33
34 /* the drived class 2 */
35 No_thr_task::No_thr_task(const string& n) :
36 Task(n)
37 {
38 }




//main.cpp
****************************************************************
#include "task.h"

int main() {
Thr_task t1("preform Thread task");
No_thr_task n1("preform non-thread task");
Thr_task dummy("");
dummy.print_mm();
}




//error
****************************************************************

cd ~/myProg/try/
make -k
g++ -gdwarf-2 -c -o main.o main.cpp
g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
task.o: In function `Task::build_mm(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
/home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
task.o: In function `Task::print_mm() const':
/home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
collect2: ld returned 1 exit status
make: *** [proj] Error 1

Compilation exited abnormally with code 2 at Fri Nov 10 20:35:08
 
G

Gary Wessle

another way I can do this is to make each task remember its menu item and
create a vector<Task*> in main.cpp, puch each item on it and loop and call
print_menu_item or even preform upon selection, i.e
vector<Task*> vTp.
*(vTp.print_menu_item)
that can do it, what you think?
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

Gary said:
another way I can do this is to make each task remember its menu item and
create a vector<Task*> in main.cpp, puch each item on it and loop and call
print_menu_item or even preform upon selection, i.e
vector<Task*> vTp.
*(vTp.print_menu_item)
that can do it, what you think?


It seems maybe you have your classes trying to do too much. Try to farm
off the menu generation to another set of classes to the task
execution. This will also make it easier to manage translation of the
menus should you need to do that. In any case the task class will be
simpler as it won't have to worry about display and the seperate
display classes will be simpler as they won't have to worry about
executing the classes.


K
 
S

Salt_Peter

Gary said:
...

the idea I had in mind is to create objects of derived classes and
once I finish creating them, I then print the main_menu. not to print
the menu ever time I create an object. and that is why I thought to
use the static std::string main_menu.
once the menu prints it should show "as its items" the string passed
to the derived class c'tor.

How you plan to use your classes and objects are not my concern. I just
output the string to check whether these worked or not. What i might
suggest is simply use one of those classes and generate a vector of
menu items. I can see something like < > to inactivate them and <-> to
disactivate the item. You might implement a callback mechanism to
"talk" to the menu.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,237
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top