473,508 Members | 2,437 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Accessing parent functions from a nested class

6 New Member
Hi,

This is my first post, so I hope it is ok. I am writting a C++ application and I have been asked to incorporate a log file mechanisim. The structure of the code I have so far is something like:

Expand|Select|Wrap|Line Numbers
  1. class A_Class {
  2.    void someFunctionsInA();
  3. };
  4.  
  5. class B_Class {
  6.    void someFunctionsInB();
  7. };
  8.  
  9. class App_Class {
  10. public:
  11.    int x;
  12.    A_Class a;
  13.    B_Class b;
  14.  
  15.    int writeToLogFile(string s);
  16. };
  17.  
I want the functions in the classes a and b to be able to use the function writeToLogFile(string) but I am not sure how this should be done. Can you advise me please?

Do I have to create a separate writeToLogFile(string) function in each of the classes a and b? I would prefer to keep all the code that deals with the log file in one place.
Feb 22 '08 #1
9 1923
bsaunder
6 New Member
ignoring the "int x;" - that was not meant to be there :-P
Feb 22 '08 #2
bsaunder
6 New Member
I think I have found one answer: use a static function.
Expand|Select|Wrap|Line Numbers
  1. class A_Class {
  2. public:
  3.    void someFunctionsInA();
  4. };
  5.  
  6. class B_Class {
  7. public:
  8.    void someFunctionsInB();
  9. };
  10.  
  11. class App_Class {
  12. public:
  13.    A_Class a;
  14.    B_Class b;
  15.    static int writeToLogFile(string s);
  16. };
  17.  
Then in the A_Class and B_Class functions I can use something like the following to use writeToLogFile(string s) function:

void A_Class::someFunctionsInA() {
App_Class::writeToLogFile("This log message was generated in the A class function.");
}


I guess this solution is ok if writeToLogFile can be made into a static function but if I wanted to have several applications running at the same time each with it's own log file then I guess that using a static function isn't going to work?

Ben.
Feb 22 '08 #3
weaknessforcats
9,208 Recognized Expert Moderator Expert
Where's the logfile object????

I would expect you wouild have a logifle class to handle the log file.
Expand|Select|Wrap|Line Numbers
  1. class App_Class
  2. {
  3. private:
  4.    A_Class a;
  5.    B_Class b;
  6.  
  7.    LogFile  theLog
  8.  
  9. public:
  10.  
  11.     void AMethod();
  12. };
  13.  
The you could:
Expand|Select|Wrap|Line Numbers
  1. void App_Class::AMethod()
  2. {
  3.      //get a data string from a
  4.      theLog->Write(data);
  5. }
  6.  
By using a LogFile pointer you assocuate your App_Class to a particular LogFile. Different App_Class objects could use different log files.

Now you can design a object-oriented hierarchy of log files so that you can record different error information as needed.

I don't think you need a static function because the App_Class has no idea how to write to a a LogFile since it is an App. Only a LogFile should know how to write to a log file.
Feb 22 '08 #4
bsaunder
6 New Member
Thank you for your reply ...

Where's the logfile object????
I don't think there is any need for so many "?" please try not to sound so rude!

I would expect you wouild have a logifle class to handle the log file.
As you have guessed I did actually already create a log file class however I found that I wanted to do some pre-processing of the string before I sent it out to the log file object. I don't just want to send the string to the log file (for example I want to display every log message on the HMI screen, among other things which means interacting with other object). Thus I wrote a single function that would do all the things I wanted to do with the log string, including sending it to the log file object.

I didn't want to confuse the issue by listing all the classes and all the objects in my code. What I was asking was how to use this function in the inner classes A_Class and B_Class. The fact that it is a log file function is (I thought) irrelevant because there maybe cases when I might want to use any generic application function in the inner classes.

I don't think you need a static function because the App_Class has no idea how to write to a a LogFile since it is an App. Only a LogFile should know how to write to a log file.
Indeed, the App_Class has no idea how to write to a log file since this is the log file objects job but this is what I have done already. However it is not the App_Class that I am asking about, it is the inner classes A_Class and B_Class. If all I was worried about was the log file object then I would pass this as a pointer to the inner classes but I want to pass all of the functionality of writeToLogFile(string s). In my original postI asked if I would have to write this functionality out in each of the inner classes, I would then have to pass to them the pointers for all the objects involved (including the log file object).

I don't think that a static function is the right way forward.

With this new information are you able to provide some more feedback?

Thanks
Feb 25 '08 #5
weaknessforcats
9,208 Recognized Expert Moderator Expert
You might be needing a Visitor. There's an article on the Visitor design pattern in the C/C++ HowTos forum.
Feb 25 '08 #6
weaknessforcats
9,208 Recognized Expert Moderator Expert
I don't think there is any need for so many "?" please try not to sound so rude!
I did not intend to be rude. Repeating characters must be some sort of arcane text-messaging rule. I my case I have a stuttering keyboard. Sorry.
Feb 25 '08 #7
bsaunder
6 New Member
Thanks weaknessforcats,

I had a look at the Visitor HowTo post and to be honest I got myself a little confused about how to apply it to my own problem. However, I did not know about "forward references" and so after reading this post I realised that I could just make a pointer to the App_Class object in the A_Class and B_Class objects. Below is the current version of my test code that compiles and does what I want:

Expand|Select|Wrap|Line Numbers
  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <string>
  4. #include "LogFile.h"
  5.  
  6. using namespace std;
  7.  
  8. const string LOGPATH = "D:\\Documents and Settings\\ben\\My Documents\\temp\\";
  9. const string LOGNAME = "benTestLogFile";
  10. const string LOGEXTN = "txt";
  11.  
  12. class App_Class; // forward reference
  13.  
  14. class A_Class {
  15. private:
  16.     App_Class* appyInAPtr;
  17. public:
  18.     A_Class(App_Class* appyCaller);
  19.     void someFunctionsInA();
  20. };
  21.  
  22. class B_Class {
  23. private:
  24.     App_Class* appyInBPtr;
  25. public:
  26.     B_Class(App_Class* appyCaller);
  27.     void someFunctionsInB();
  28. };
  29.  
  30. class App_Class {
  31. public:
  32.     App_Class();
  33.     A_Class a;
  34.     B_Class b;
  35.  
  36.     LogFile log;
  37.  
  38.     bool writeToLogFile(string s);
  39. };
  40.  
  41. App_Class::App_Class() : a(this), b(this)
  42. {
  43. }
  44.  
  45. A_Class::A_Class(App_Class *appyCaller) {
  46.     appyInAPtr = appyCaller;
  47. }
  48.  
  49. void A_Class::someFunctionsInA() {
  50.     appyInAPtr->writeToLogFile("Running the A class function.");
  51. }
  52.  
  53. B_Class::B_Class(App_Class *appyCaller) {
  54.     appyInBPtr = appyCaller;
  55. }
  56.  
  57. void B_Class::someFunctionsInB() {
  58.     appyInBPtr->writeToLogFile("Running the B class function.");
  59. }
  60.  
  61. bool App_Class::writeToLogFile(string s) {
  62.     log.write(s);
  63.     cout << "[IN LOG FILE]: " << s << endl;
  64.     return true;
  65. }
  66.  
  67.  
  68. //int _tmain(int argc, _TCHAR* argv[])
  69. int main()
  70. {
  71.     // Local Variables
  72.     char endChar;
  73.     App_Class appy;
  74.  
  75.     // set up the log file
  76.     appy.log.setLogFile(LOGPATH, LOGNAME, LOGEXTN);
  77.  
  78.     cout << "Output is: " << endl << endl;
  79.     appy.writeToLogFile("Testing log file:");
  80.     appy.a.someFunctionsInA();
  81.     appy.b.someFunctionsInB();
  82.     cout << endl << "done!" << endl;
  83.     cout << endl;
  84.  
  85.     cout << "Press any key (and enter) to end." << endl;
  86.     cin >> endChar;
  87.  
  88.     return 0;
  89. }
  90.  
The output of the application is:

> Output is:
>
> [IN LOG FILE]: Testing log file:
> [IN LOG FILE]: Running the A class function.
> [IN LOG FILE]: Running the B class function.
>
> done!
>
> Press any key (and enter) to end.

And I get in my log file benTestLogFile_2008_02_27.txt (the date is automatically appended by the log file name):

> [2008/02/27 12:42:21]: Testing log file:
> [2008/02/27 12:42:21]: Running the A class function.
> [2008/02/27 12:42:21]: Running the B class function.

This compiles ok but I do get a couple of the following compiler warning:

warning C4355: 'this' : used in base member initializer list

I guess these are nothing much to worry about?
Feb 27 '08 #8
weaknessforcats
9,208 Recognized Expert Moderator Expert
warning C4355: 'this' : used in base member initializer list
The this pointer is not valid in a constructor initilizer list since the object is not yet built. Potentially, you could call a derived method that uises variables that aren't initialized.

I would tuse the this pointer in the constructor initializer list.

What you are trying to do is get the derived address into the base object.

The Visitor uses a base method that has a Visitor* argument. That base method is overriden by a derived method that also takes a Visitor* argument.

The derived method calls a Visitor->VisitDerived(this).

VisitDerived is a derived class of Visitor.

So you end up in a VisitDerived object with the address of the derived object in the other hierarchy.

Visitor is great.

Say you have a Car derived form Vehicle and you suddenly need to do a cost analysis on various Cars but there is no cost in formation in the Car class.

You write a CarCostAnalyzer class (derived from Visitor) and you call the Car object using Vehicle->Visit(CarCostAnalyzer*).

Boom! You end up at CarCostAnalyzer::VisitDerived with the this pointer of the Car object.

Now you can access all Car methods regardless of whether they are in the Vehicle base class or not.
Feb 27 '08 #9
bsaunder
6 New Member
Thanks for your patients Weaknessforcats,

I wouldn't use the this pointer in the constructor initializer list.
I guess anything that generates a warning has to be questionable and so I guess I shouldn't use the this pointer in the constructor initializer list either.

What you are trying to do is get the derived address into the base object.
Does this mean getting the derived address of the App_Class object into the base objects of A_Class and B_Class? (Although App_Class is not a derived class, neither is A_Class or B_Class).

The Visitor uses a base method that has a Visitor* argument. That base method is overridden by a derived method that also takes a Visitor* argument.

The derived method calls a Visitor->VisitDerived(this).

VisitDerived is a derived class of Visitor.
So I make a Visitor class which is derived from some base class that has a method with a Visitor* argument. Then the Visitor class should overwrite this method?

Should my Visitor class be derived from App_Class or from A_Class/B_Class?
Should the VisitDerived class be the App_Class or the A_Class/B_Class or is this some completely different class?

So you end up in a VisitDerived object with the address of the derived object in the other hierarchy.
So VisitDerived should be the A_Class/B_Class thus ending up with the address of the derived object in the other hierarchy (APP_Class)? That's what I want right?

So in my case I would want to create a Visitor class and derive it from App_Class. I would need to put into the App_Class an empty method that takes an argument Visitor* and then in the Visitor class I should overwrite this method.

So far I have this:

Expand|Select|Wrap|Line Numbers
  1. class Visitor;        // forward reference
  2.  
  3. class A_Class {
  4. public:
  5.     void someFunctionsInA();
  6. };
  7.  
  8. class B_Class {
  9. public:
  10.     void someFunctionsInB();
  11. };
  12.  
  13. class App_Class {
  14. public:
  15.     A_Class a;
  16.     B_Class b;
  17.  
  18.     LogFile log;
  19.  
  20.     bool writeToLogFile(string s);
  21.  
  22.     void runVisitor(Visitor *v) {};
  23. };
  24.  
  25. class Visitor : public App_Class {
  26.     void runVisitor(Visitor *v) {
  27.         // Not sure what to put in here.
  28.         // v->writeToLogFile(s)
  29.     };
  30. };
This compiles ok. The next thing I thought I was to do was to make the A_Class and B_Class derived from Visitor but I can not do this. It seems that I am creating a circle of declarations. I must have miss-understood something.

lets have a look at the example ...

Say you have a Car derived form Vehicle and you suddenly need to do a cost analysis on various Cars but there is no cost in formation in the Car class.
Or in my case: I have a class A_Class that is not derived from anything and I suddenly need to record its progress in a log file but there is no log file function in the A_Class class.

You write a CarCostAnalyzer class (derived from Visitor) and you call the Car object using Vehicle->Visit(CarCostAnalyzer*).
Ah! So I should write a completely new class? called logFileInterface and derive this from Visitor (is this the VisitDerived class mentioned above?) which in turn is derived from App_Class? But then I can't call A_Class->runVisitor(logFileInterface*) because the A_Class isn't a Visitor object.

...

I hope you can see why I am getting confused. I am sure that once I figure this out it will all suddenly become clear. I will keep on trying to figure this out by reading your comments above and the HowTo post on C++ Visitors.
Feb 28 '08 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

5
27581
by: Paul | last post by:
Hi all, Here is what I am trying to do. I have a parent class calling a child class. when one function in child class is called, i need to call parent class' function. How can I get parent class'...
2
6646
by: Chris New | last post by:
G'Day All I am having trouble dynamically assigning a value to a table's cell from one frame to another frame. I've created a website that is primarily viewed in a frameset consisting of 2...
5
3632
by: Suzanne Vogel | last post by:
Hi, Given: I have a class with protected or private data members, some of them without accessor methods. It's someone else's class, so I can't change it. (eg, I can't add accessor methods to the...
3
1896
by: Philip Parker | last post by:
hows it done? :/ i cant seem to access things in a "config" class i made the setup is something like this class IRCBot { OPTIONS Config IRCCONN Irc .... }
5
18557
by: Trey | last post by:
Is it possible to access the parent from an instance of a "child" class? For example in the code below I would like to be able to reference which exact army a troop belonged to by doing something...
1
1957
by: Roy | last post by:
How is it done? BTW, I'm reposting this here, as the datagrid newsgroup appears functionally comatose... I have a nested datagrid setup. When one updates the child grid using edit, it also...
1
1783
by: Yuk Tang | last post by:
Leading on from a recent topic, "How does child class access parent's variables", I would like to ask, what's the most elegant way of changing a parent/grandparent/great-grandparent's property? ...
22
4781
by: Boris | last post by:
I'm porting code from Windows to UNIX and ran into a problem with dynamic_cast. Imagine a class hierarchy with three levels: class Level2 derives from Level1 which derives from Base. If you look...
5
2703
by: =?Utf-8?B?bXVzb3NkZXY=?= | last post by:
Hi guys I'm trying to make my code as streamlined as possible, and add CSS file references dynamically when they are required, for example, if a page contains a webcontrol, then the related CSS...
0
7223
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7114
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7321
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
7034
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5623
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5045
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3191
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
1
762
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
412
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.