473,472 Members | 1,702 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Reference Question

I have the following test code. What I have a question about is in
Func2Ref. In the pointer example, the last called method is actually the
one whom allocated memory for the object and returns the pointer to the
calling parent for it to be printed. In the reference example, the parent
actually creates the object but in Func2Ref, I need that object to be a
derived type. This is like how AST traversal occurs **hint**.

Can someone offer some input on how I should do this if I choose to use
&object reference instead of *object pointers??

class CNode {
public:
CNode() { }
virtual ~CNode() { }
virtual void print(void) = 0;
};

class CChildNode : public CNode {
public:
CChildNode() { }
virtual ~CChildNode() { }
};

class CBabyNode : public CChildNode {
public:
CBabyNode(int nVal) m_nVal(nVal) { }
virtual ~CBabyNode() { }
void print(void) { cout << m_nVal; }
private:
int m_nVal;
};

void Func2Ptr(CNode *node) {
node = new CBabyNode(5);
}
void Func1Ptr(CNode *node) {
Func2Ptr(node);
}
void Func2Ref(CNode &node) {
// here I need to be able to change
// CNode to a CBabyNode and be able
// to have it print its value when
// the main program calls print.
}
void Func1Ref(CNode &node) {
Func2Ref(node);
}

int main(int argc, char* argv[]) {
{
// Do pointer test
CNode *pNode = NULL;
Func1Ptr(pNode);
if(pNode != NULL) {
pNode->print();
delete pNode;
}

// Do Ref test
CNode node;
Func1Ref(node);
node.print();

return 0;
}

Thanks!
--

Jul 22 '05 #1
6 1274
"news.tkdsoftware.com" <ch***@noreply.nospam.tkdsoftware.com> wrote in
message news:wc****************************@tkdsoftware.co m...
I have the following test code. What I have a question about is in
Func2Ref. In the pointer example, the last called method is actually the
one whom allocated memory for the object and returns the pointer to the
calling parent for it to be printed. In the reference example, the parent
actually creates the object but in Func2Ref, I need that object to be a
derived type. This is like how AST traversal occurs **hint**.

Can someone offer some input on how I should do this if I choose to use
&object reference instead of *object pointers??

class CNode {
public:
CNode() { }
virtual ~CNode() { }
virtual void print(void) = 0;
};

class CChildNode : public CNode {
public:
CChildNode() { }
virtual ~CChildNode() { }
};

class CBabyNode : public CChildNode {
public:
CBabyNode(int nVal) m_nVal(nVal) { }
virtual ~CBabyNode() { }
void print(void) { cout << m_nVal; }
private:
int m_nVal;
};

void Func2Ptr(CNode *node) {
node = new CBabyNode(5);
}
That's going to leak memory. Perhaps you meant for Func2Ptr to take a
reference to a pointer?
void Func1Ptr(CNode *node) {
Func2Ptr(node);
}
void Func2Ref(CNode &node) {
// here I need to be able to change
// CNode to a CBabyNode and be able
// to have it print its value when
// the main program calls print.
}

<snip>

Could you elaborate on this? References may not be reseated. This is
explained in the FAQ (http://www.parashift.com/c++-faq-lite) section 8
(References), question 5 (How can you reseat a reference to make it refer to
a different object?). It sounds like you are trying to do something that is
impossible. What are you really trying to do?

--
David Hilsee
Jul 22 '05 #2

"news.tkdsoftware.com" <ch***@noreply.nospam.tkdsoftware.com> wrote in
message news:wc****************************@tkdsoftware.co m...
I have the following test code. What I have a question about is in
Func2Ref.
Actually you have a few misunderstandings. Chiefly that you don't understand
how to return a value from a function.
In the pointer example, the last called method is actually the
one whom allocated memory for the object and returns the pointer to the
calling parent for it to be printed. In the reference example, the parent
actually creates the object but in Func2Ref, I need that object to be a
derived type. This is like how AST traversal occurs **hint**.

Can someone offer some input on how I should do this if I choose to use
&object reference instead of *object pointers??

class CNode {
public:
CNode() { }
virtual ~CNode() { }
virtual void print(void) = 0;
};

class CChildNode : public CNode {
public:
CChildNode() { }
virtual ~CChildNode() { }
};

class CBabyNode : public CChildNode {
public:
CBabyNode(int nVal) m_nVal(nVal) { }
virtual ~CBabyNode() { }
void print(void) { cout << m_nVal; }
private:
int m_nVal;
};

void Func2Ptr(CNode *node) {
node = new CBabyNode(5);
}
You mean

CNode *Func2Ptr() {
return new CBabyNode(5);
}
void Func1Ptr(CNode *node) {
Func2Ptr(node);
}
You mean

CNode *Func1Ptr() {
return Func2Ptr();
}

But this does exactly the same as the function above, so it hard to know
what you intended.
void Func2Ref(CNode &node) {
// here I need to be able to change
// CNode to a CBabyNode and be able
// to have it print its value when
// the main program calls print.
}
CNode cannot change to CBabyNode, it is impossible.
void Func1Ref(CNode &node) {
Func2Ref(node);
}

int main(int argc, char* argv[]) {
{
// Do pointer test
CNode *pNode = NULL;
Func1Ptr(pNode);
if(pNode != NULL) {
This will always be false, because the way you wrote Func1Ptr it did not
return any value. Whith my correction it will at least return a value and
pNode will be non NULL.
pNode->print();
delete pNode;
}

// Do Ref test
CNode node;
Func1Ref(node);
node.print();

return 0;
}


You are trying to do tree traversal, but you aren't coding anything like
that. I think you have some serious misunderstanding about what you are
doing. Unfortunately this makes it impossible to help because, whatever it
is that you are trying to accomplish, you do not need to turn a CNode into a
CBabyNode, so even if there was a way to do that it wouldn't help you. You
are just asking the wrong questions.

I would ask again but instead of asking about specific language questions,
explain what it is that you are trying to do, and if you can, what it is
that you don't understand.

john
Jul 22 '05 #3
John -
You are trying to do tree traversal, but you aren't coding anything like
that. so even if there was a way to do that it wouldn't help you. You
are just asking the wrong questions.


Yes, I am intending to generate/populate a tree. For example:

PRINT 2+3*5

would yield an AST tree so that I can traverse it using a visitor pattern
to get the following output:
5
3
*
2
+
PRINT

The goal of my prior post was to understand how I should construct my
classes for the tree and how my functions could be written using reference
variables as arguments instead of pointers to accomplish this.

If someone could illustrate an example set of code, that would be great
to help clear my misunderstandings.

Thanks
Chris
Jul 22 '05 #4

"news.tkdsoftware.com" <ch***@noreply.nospam.tkdsoftware.com> wrote in
message news:wc*************************************@tkdso ftware.com...
John -
You are trying to do tree traversal, but you aren't coding anything like
that. so even if there was a way to do that it wouldn't help you. You
are just asking the wrong questions.


Yes, I am intending to generate/populate a tree. For example:

PRINT 2+3*5

would yield an AST tree so that I can traverse it using a visitor pattern
to get the following output:
5
3
*
2
+
PRINT

The goal of my prior post was to understand how I should construct my
classes for the tree and how my functions could be written using reference
variables as arguments instead of pointers to accomplish this.

If someone could illustrate an example set of code, that would be great
to help clear my misunderstandings.

Thanks
Chris


Do you actually understand the visitor pattern and it's motivation? Before
you worry about using references not pointers I would write some code that
actually implements the visitor pattern.

I'm not a pattern expert but here my implementation using pointers. I hope
this helps.

#include <iostream>
#include <string>

class Node;

class Visitor
{
public:
virtual ~Visitor() {}
virtual void visit_number(Node* node) = 0;
virtual void visit_unary_func(Node* node) = 0;
virtual void visit_binary_func(Node* node) = 0;
};

class Node
{
public:
virtual ~Node() {}
virtual void accept(Visitor* v) = 0;
virtual void print(std::ostream& out) = 0;
};

class Number : public Node
{
public:
Number(int n) : num(n) {}
void accept(Visitor* v)
{
v->visit_number(this);
}
void print(std::ostream& out)
{
out << num << '\n';
}
private:
int num;
};

class UnaryFunc : public Node
{
public:
UnaryFunc(const std::string& n, Node* a) : name(n), arg(a) {}
void accept(Visitor* v)
{
arg->accept(v);
v->visit_unary_func(this);
}
void print(std::ostream& out)
{
out << name << '\n';
}
private:
std::string name;
Node* arg;
};

class BinaryFunc : public Node
{
public:
BinaryFunc(const std::string& n, Node* a1, Node* a2) : name(n), arg1(a1) ,
arg2(a2) {}
void accept(Visitor* v)
{
arg1->accept(v);
arg2->accept(v);
v->visit_binary_func(this);
}
void print(std::ostream& out)
{
out << name << '\n';
}
private:
std::string name;
Node* arg1;
Node* arg2;
};

class PrintVisitor : public Visitor
{
public:
PrintVisitor(std::ostream& o) : out(o) {}
virtual void visit_number(Node* node)
{
node->print(out);
}
virtual void visit_unary_func(Node* node)
{
node->print(out);
}
virtual void visit_binary_func(Node* node)
{
node->print(out);
}
private:
std::ostream& out;
};

int main()
{
Number two(2);
Number three(3);
Number five(5);
BinaryFunc times("*", &five, &three);
BinaryFunc plus("+", &times, &two);
UnaryFunc print("PRINT", &plus);
PrintVisitor pv(std::cout);
print.accept(&pv);
}
Jul 22 '05 #5
The visitor patten you posted makes sense and did drive me in the right
direction I do believe, see below.
Number two(2);
Number three(3);
Number five(5);
BinaryFunc times("*", &five, &three);
BinaryFunc plus("+", &times, &two);
UnaryFunc print("PRINT", &plus);
PrintVisitor pv(std::cout);
print.accept(&pv);
}


I guess what I'm trying to understand is the best way for the parser to
create the AST tree itself as it traverses the tokens from the lexer. See
my code below. Comments are certainly welcome.

As you can see, I pass the parent downward for tree population and have
the function return the resultant node. I added logic in the classes
you originally provided to take care of memory cleanup of the pointers
that I am passing to those objects. Does what i have provided make
logical sense?

What would you suggest I do next?

void CParser::ParseProgram(void) {
CProgram program; // class derived from CNode
while(token.type != TOKEN_EOF) {
CNode *statement = ParseStatement(program);
// here I guess I need a way to
// insert the returned statement
// into my program class ??
PrintVisitor pv(std::ostream);
statement->accept(&pv);
delete statement; }
return program;
}

CNode* CParser::ParseStatement(CNode &parent) {
CNode *p = NULL;
switch(token.type) {
case OP_PRINT:
p = new UnaryFunc("PRINT",ParseExpression(parent));
break;
default:
throw CParserException(STATEMENT_EXPECTED);
break;
}
return p;
}

CNode* CParser::ParseExpression(CNode &parent) {
CNode *p = ParseTerm(parent);
while(token.type == OP_ADD || token.type == OP_SUB) {
int op = token.type;
GetNextToken();
p = new BinaryFunc(op,p,ParseTerm(parent));
}
return p;
}

CNode* CParser::ParseTerm(CExpr &parent) {
CNode *p = ParseFactor(parent);
while(token.type == OP_TIMES || token.type == OP_DIV) {
int op = token.type
GetNextToken();
p = new BinaryFunc(op,p,ParseFactor(parent));
}
return p;
}

CNode* CParser::ParseFactor(CExpr &parent) {
CNode *p = NULL;
switch(token.type) {
case LPAREN:
GetNextToken();
p = ParseExpression(parent);
if(token != RPAREN)
throw CParserException(RPAREN_EXPECTED);
break;
case NUMBER:
p = new Number(token);
GetNextToken();
break;
default:
throw CParserException(FACTOR_EXPECTED);
break;
}
return p;
}

thanks
chris
---
Jul 22 '05 #6

"news.tkdsoftware.com" <ch***@noreply.nospam.tkdsoftware.com> wrote in
message news:wc*************************************@tkdso ftware.com...
The visitor patten you posted makes sense and did drive me in the right
direction I do believe, see below.
Number two(2);
Number three(3);
Number five(5);
BinaryFunc times("*", &five, &three);
BinaryFunc plus("+", &times, &two);
UnaryFunc print("PRINT", &plus);
PrintVisitor pv(std::cout);
print.accept(&pv);
}
I guess what I'm trying to understand is the best way for the parser to
create the AST tree itself as it traverses the tokens from the lexer. See
my code below. Comments are certainly welcome.


Well that's a completely different problem.

As you can see, I pass the parent downward for tree population and have
the function return the resultant node. I added logic in the classes
you originally provided to take care of memory cleanup of the pointers
that I am passing to those objects. Does what i have provided make
logical sense?

What would you suggest I do next?

void CParser::ParseProgram(void) {
CProgram program; // class derived from CNode
while(token.type != TOKEN_EOF) {
CNode *statement = ParseStatement(program);
// here I guess I need a way to
// insert the returned statement
// into my program class ??
Yes I think so.
PrintVisitor pv(std::ostream);
statement->accept(&pv);
delete statement; }
return program;
}

CNode* CParser::ParseStatement(CNode &parent) {
CNode *p = NULL;
switch(token.type) {
case OP_PRINT:
p = new UnaryFunc("PRINT",ParseExpression(parent));
break;
default:
throw CParserException(STATEMENT_EXPECTED);
break;
}
return p;
}

CNode* CParser::ParseExpression(CNode &parent) {
CNode *p = ParseTerm(parent);
while(token.type == OP_ADD || token.type == OP_SUB) {
int op = token.type;
GetNextToken();
p = new BinaryFunc(op,p,ParseTerm(parent));
}
return p;
}

CNode* CParser::ParseTerm(CExpr &parent) {
CNode *p = ParseFactor(parent);
while(token.type == OP_TIMES || token.type == OP_DIV) {
int op = token.type
GetNextToken();
p = new BinaryFunc(op,p,ParseFactor(parent));
}
return p;
}

CNode* CParser::ParseFactor(CExpr &parent) {
CNode *p = NULL;
switch(token.type) {
case LPAREN:
GetNextToken();
p = ParseExpression(parent);
if(token != RPAREN)
throw CParserException(RPAREN_EXPECTED);
break;
case NUMBER:
p = new Number(token);
GetNextToken();
break;
default:
throw CParserException(FACTOR_EXPECTED);
break;
}
return p;
}


It looks a lot better than the previous code. Looks like you are developing
a recursive descent parser. I don't see why you are passing the parent down
however, you never seem to do anything with it other than pass it along.

john
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Amr Mostafa | last post by:
Hello :) I'm trying to write a script that deals with a web service. I'm using NuSoap class. my question is : Can I pass some variables By Reference to the web service and get the result back...
6
by: Chris S. | last post by:
I'm trying to make a graphical editor and browser for Pickled files. One aspect I'm not sure about is how to detect multiple references to the same data. For instance, say I had the Pickled...
1
by: Tony Johansson | last post by:
Hello Experts! I reading a book called programming with design pattern revealed by Tomasz Muldner and here I read something that I don't understand completely. It says "A garbarage...
1
by: Tony Johansson | last post by:
Hello Experts! I reading a book called programming with design pattern revealed by Tomasz Muldner and here I read something that I don't understand completely. It says "A garbarage...
6
by: Lenn | last post by:
Hi, Could someone clarify my confusion regarding passing reference types to a method with ref keyword and explain when it's practical to use it. It's my understanding that in .NET reference...
9
by: ziman137 | last post by:
Hi all, The results from following codes got me a bit confused. #include <stdio.h> #include <iostream> using namespace std; struct A {
1
by: Michel Couche | last post by:
Hello, I am starting the development of a newsletter The use of the class MailMessage of System.Net.Mail is quite straightforward for usual contact forms but my question here is "How can I...
3
by: pleaseexplaintome_2 | last post by:
using the code below (some parts not included), I create a new excel workbook with spreadheets. I then want to delete a spreadsheet, but a reference remains open and excel stays in task manager...
68
by: Jim Langston | last post by:
I remember there was a thread a while back that was talking about using the return value of a function as a reference where I had thought the reference would become invalidated because it was a...
12
by: Bryan Parkoff | last post by:
I write my large project in C++ source code. My C++ source code contains approximate four thousand small functions. Most of them are inline. I define variables and functions in the global scope....
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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
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,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
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,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
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...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.