No polymiorphism for virtual operator= ?

S

sun1991

Hi All,
I tried the following code, but it did not work as I think:

---
using namespace std;
namespace
{
class Fraction
{
public:
Fraction(int num1, int num2): m_num1(num1), m_num2(num2){};
virtual Fraction& operator=(const Fraction& f);
private:
int m_num1;
int m_num2;
};
Fraction& Fraction::eek:perator =(const Fraction& f)
{
cout << "Fraction::eek:perator=" << "\n";
return *this;
}

class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3): Fraction(num1, num2),
m_num3(num3){}
virtual Fraction2& operator=(const Fraction2& f);
private:
int m_num3;
};

Fraction2& Fraction2::eek:perator=(const Fraction2& f)
{
cout << "Fraction2::eek:perator=" << "\n";
return *this;
}
}

void Sample(Fraction& f1, Fraction& f2)
{
f1 = f2;
}

int _tmain(int argc, _TCHAR* argv[])
{
Fraction2 f1(1, 2, 3);
Fraction2 f2(3, 4, 5);

Sample(f1, f2);

system("pause");
return 0;
}

output: Fraction::eek:perator=
 
A

Alf P. Steinbach

* sun1991:
int _tmain(int argc, _TCHAR* argv[])

This is not a standard "main" function.

Therefore, your program can produce /any/ output, if it compiles with
your compiler.

Post standard C++ code, please.
 
N

Neelesh Bodas

Hi All,
I tried the following code, but it did not work as I think:

---
using namespace std;
namespace
{
class Fraction
{
public:
Fraction(int num1, int num2): m_num1(num1), m_num2(num2){};
virtual Fraction& operator=(const Fraction& f);
private:
int m_num1;
int m_num2;
};
Fraction& Fraction::eek:perator =(const Fraction& f)
{
cout << "Fraction::eek:perator=" << "\n";
return *this;
}

class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3): Fraction(num1, num2),
m_num3(num3){}
virtual Fraction2& operator=(const Fraction2& f);
private:
int m_num3;
};

Fraction2& Fraction2::eek:perator=(const Fraction2& f)
{
cout << "Fraction2::eek:perator=" << "\n";
return *this;
}

}

void Sample(Fraction& f1, Fraction& f2)
{
f1 = f2;

This is same as saying f1.operator=(f2);

Since C++ is statically typed, type of f1 is determined at compile
time, which turns out to be 'Fraction'. Thus, there is no way
"operator=" from Fraction2 will get called.

}

int _tmain(int argc, _TCHAR* argv[])
non-standard.

{
Fraction2 f1(1, 2, 3);
Fraction2 f2(3, 4, 5);

Sample(f1, f2);

system("pause");
return 0;

}

output: Fraction::eek:perator=


-N
 
M

Ming

Hi All,
I tried the following code, but it did not work as I think:

---
using namespace std;
namespace
{
class Fraction
{
public:
Fraction(int num1, int num2): m_num1(num1), m_num2(num2){};
virtual Fraction& operator=(const Fraction& f);
private:
int m_num1;
int m_num2;
};
Fraction& Fraction::eek:perator =(const Fraction& f)
{
cout << "Fraction::eek:perator=" << "\n";
return *this;
}

class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3): Fraction(num1, num2),
m_num3(num3){}
virtual Fraction2& operator=(const Fraction2& f);
private:
int m_num3;
};

Fraction2& Fraction2::eek:perator=(const Fraction2& f)
{
cout << "Fraction2::eek:perator=" << "\n";
return *this;
}

}

void Sample(Fraction& f1, Fraction& f2)
{
f1 = f2;

}

int _tmain(int argc, _TCHAR* argv[])
{
Fraction2 f1(1, 2, 3);
Fraction2 f2(3, 4, 5);

Sample(f1, f2);

system("pause");
return 0;

}

output: Fraction::eek:perator=

the thing to remember is

base& base::eek:perator=(base& rhs)

does not override or virtually substitute

derived& derived::eek:perator=(derived& rhs)


when f1 is passed in, it is passed in as fraction2, but when it checks
the virtual table, there is only one versin of fraction&
fraction::eek:perator=( fraction &), which is in fraction. That's why you
see what you see.

to make it work, you have to do this:

class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3):
Fraction(num1, num2),
m_num3(num3){}
virtual Fraction& operator=(const Fraction& f);
private:
int m_num3;
};

but this really doesn't make too much sense.
 
J

jpalecek

Hi All,
I tried the following code, but it did not work as I think:

---

.... boring and irrelevent stuff deleted ...
using namespace std;
class Fraction
{
public:
virtual Fraction& operator=(const Fraction& f);
};
class Fraction2: public Fraction
{
public:
virtual Fraction2& operator=(const Fraction2& f);
};
}
Is it because there's no polymiorphism for operator= or what?

No. It is because, you have acually two operator='s in F2. The first
inherited from Fraction and taking Fraction& as rhs and the second
new one with F2 as rhs. To actually override the Fraction's
opertator=,
you need the operator= to have exactly the same arguments, ie.

Fraction2& Fraction2::eek:perator=(const Fraction&);

I think (but am not sure) it's possible to return Fraction2 here.

You will probably have to use dynamic_cast to downcast the
rhs from Fraction to Fraction2

Regards
Jiri Palecek
 
J

jpalecek

* sun1991:


int _tmain(int argc, _TCHAR* argv[])

This is not a standard "main" function.

Therefore, your program can produce /any/ output, if it compiles with
your compiler.

That's nonsense, read section 4.6 in the standard.

If you have nothing to say, please refrain from posting.

Jiri Palecek
 
M

Ming

Hi All,
I tried the following code, but it did not work as I think:
---
using namespace std;
namespace
{
class Fraction
{
public:
Fraction(int num1, int num2): m_num1(num1), m_num2(num2){};
virtual Fraction& operator=(const Fraction& f);
private:
int m_num1;
int m_num2;
};
Fraction& Fraction::eek:perator =(const Fraction& f)
{
cout << "Fraction::eek:perator=" << "\n";
return *this;
}
class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3): Fraction(num1, num2),
m_num3(num3){}
virtual Fraction2& operator=(const Fraction2& f);
private:
int m_num3;
};
Fraction2& Fraction2::eek:perator=(const Fraction2& f)
{
cout << "Fraction2::eek:perator=" << "\n";
return *this;
}

void Sample(Fraction& f1, Fraction& f2)
{
f1 = f2;

int _tmain(int argc, _TCHAR* argv[])
{
Fraction2 f1(1, 2, 3);
Fraction2 f2(3, 4, 5);
Sample(f1, f2);
system("pause");
return 0;

output: Fraction::eek:perator=
---
Is it because there's no polymiorphism for operator= or what?

the thing to remember is

base& base::eek:perator=(base& rhs)

does not override or virtually substitute

derived& derived::eek:perator=(derived& rhs)

oops, it should be the other way around. sorry
 
A

Alf P. Steinbach

* (e-mail address removed):
* sun1991:


int _tmain(int argc, _TCHAR* argv[])
This is not a standard "main" function.

Therefore, your program can produce /any/ output, if it compiles with
your compiler.

That's nonsense, read section 4.6 in the standard.

I could treat this statement as a newbie question. But it would be
useless with your current attitude. First you need to adjust your attitude.

If you have nothing to say, please refrain from posting.

Are you sure you don't want to learn anything? You're posting questions
here, which is usually for the purpose of learning. Then you dismiss
what you could learn from, which is not rational behavior.
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

* sun1991:


int _tmain(int argc, _TCHAR* argv[])

This is not a standard "main" function.

Therefore, your program can produce /any/ output, if it compiles with
your compiler.

That's nonsense, read section 4.6 in the standard.

If you have nothing to say, please refrain from posting.

It's section 3.6.1 in my copy, and it says quite clearly that the
function should be named "main" and nothing else (such as "_tmain").
 
J

jpalecek

* sun1991:
int _tmain(int argc, _TCHAR* argv[])
This is not a standard "main" function.
Therefore, your program can produce /any/ output, if it compiles with
your compiler.
That's nonsense, read section 4.6 in the standard.
If you have nothing to say, please refrain from posting.

It's section 3.6.1 in my copy, and it says quite clearly that the
function should be named "main" and nothing else (such as "_tmain").

3.6.1, yes, my fault. My point was this section doesn't prevent the
program with _tmain from functioning (...it is implementation-defined
whether ... under freestanding environment ... is required to
define ...
main ...). It is quite questionable whether Windows (this is
Windows code) can be classified as freestanding environment, however,
under reasonable circumstances, there's a

#define _tmain main
#define _TCHAR char

in the Windows headers, which will make the program standard
compliant.

Anyway, I think the discussion about _tmain is completely offtopic
here,
because the original questioner obviously didn't have problems with
running
the function, but with virtual function call.

Regards
Jiri Palecek
 
J

jpalecek

* (e-mail address removed):
* sun1991:
int _tmain(int argc, _TCHAR* argv[])
This is not a standard "main" function.
Therefore, your program can produce /any/ output, if it compiles with
your compiler.
That's nonsense, read section 4.6 in the standard.

I could treat this statement as a newbie question. But it would be
useless with your current attitude. First you need to adjust your attitude.

You can treat my post as you wish. Just note there was no question,
because there is no question mark (?) in my post.
Are you sure you don't want to learn anything? You're posting questions
here, which is usually for the purpose of learning. Then you dismiss
what you could learn from, which is not rational behavior.

Look, I'm not the original questioner, but the questioner asked
for help with his problem. You not only failed to answer his question,
but also reproached him for some irrelevant, and maybe even
sensible thing, with an argument that was only partly true. In effect,
you said something like "piss off".

You either:
1. Didn't realize _tmain name was irrelevant
2. Didn't know _tmain is a #define for main
3. Couldn't find the error causing the problem.
4. Didn't want to spend time finding the problem.
5. Wanted to post something, regardless it doesn't help.

If cases 1-3 hold, you were simply ignorant. If 4-5, you were
malicious. Certainly, you didn't help.
 
A

Alf P. Steinbach

* (e-mail address removed):
* (e-mail address removed):
* sun1991:
int _tmain(int argc, _TCHAR* argv[])
This is not a standard "main" function.
Therefore, your program can produce /any/ output, if it compiles with
your compiler.
That's nonsense, read section 4.6 in the standard.
I could treat this statement as a newbie question. But it would be
useless with your current attitude. First you need to adjust your attitude.

You can treat my post as you wish. Just note there was no question,
because there is no question mark (?) in my post.

I noted. There should have been a question mark.

Look, I'm not the original questioner, but the questioner asked
for help with his problem. You not only failed to answer his question,

That's a lie by any reasonable definition (intent to deceive).

but also reproached him for some irrelevant, and maybe even
sensible thing, with an argument that was only partly true. In effect,
you said something like "piss off".

That is a lie.

You either:
1. Didn't realize _tmain name was irrelevant

You're wrong: it isn't irrelevant.

2. Didn't know _tmain is a #define for main

You're wrong: it isn't. There's one IDE (not compiler, but IDE) that
generates code that defines _tmain, but it isn't necessarily defined as
"main" even there. And anyway, such definition was not included in the
OP's code.

3. Couldn't find the error causing the problem.

Nobody who frequents this group would suspect me of not finding a
trivial error, and you're wrong that something else was "the problem":
first the code must pass compilation.

4. Didn't want to spend time finding the problem.

Nobody who frequents this group would suspect me of being unhelpful.

5. Wanted to post something, regardless it doesn't help.
Uh.


If cases 1-3 hold, you were simply ignorant. If 4-5, you were
malicious. Certainly, you didn't help.

And that's also a lie.

Cheers, and hope this helps,


- Alf
 
S

sun1991

to make it work, you have to do this:

class Fraction2: public Fraction
{
public:
Fraction2(int num1, int num2, int num3):
Fraction(num1, num2),
m_num3(num3){}
virtual Fraction& operator=(const Fraction& f);
private:
int m_num3;
};

but this really doesn't make too much sense.


Yeah, I got your point. Thanks. I used different parameter in
operator=, so it becomes two different function. Can I say that don't
expect virtual operator= to be polymiorphism, because it is not the
way you want? (Sounds like a C++ philosophy question)
 
A

Alf P. Steinbach

* sun1991:
Yeah, I got your point. Thanks. I used different parameter in
operator=, so it becomes two different function. Can I say that don't
expect virtual operator= to be polymiorphism, because it is not the
way you want? (Sounds like a C++ philosophy question)

If you keep the signature the same (as in the code shown above) in the
derived class, then you have a polymorphic assignment operator. It's an
assignment operator but it's not the copy assignment operator; you can
have as many assignment operators as you want in addition to the copy
assignment operator. When the copy assignment operator is not declared,
and is needed, the compiler generates a copy assignment operator.
 
S

sun1991

If you keep the signature the same (as in the code shown above) in the
derived class, then you have a polymorphic assignment operator. It's an
assignment operator but it's not the copy assignment operator; you can
have as many assignment operators as you want in addition to the copy
assignment operator. When the copy assignment operator is not declared,
and is needed, the compiler generates a copy assignment operator.

When I say philosophy, I mean people usually don't do that, because it
is often a bad design (try to make operator= polymiorphism), isn't it?
 
A

anon

* (e-mail address removed):
* sun1991:
int _tmain(int argc, _TCHAR* argv[])
This is not a standard "main" function.
Therefore, your program can produce /any/ output, if it compiles with
your compiler.
That's nonsense, read section 4.6 in the standard.
I could treat this statement as a newbie question. But it would be
useless with your current attitude. First you need to adjust your attitude.

You can treat my post as you wish. Just note there was no question,
because there is no question mark (?) in my post.
Are you sure you don't want to learn anything? You're posting questions
here, which is usually for the purpose of learning. Then you dismiss
what you could learn from, which is not rational behavior.

Look, I'm not the original questioner, but the questioner asked
for help with his problem. You not only failed to answer his question,
but also reproached him for some irrelevant, and maybe even
sensible thing, with an argument that was only partly true. In effect,
you said something like "piss off".

You either:
1. Didn't realize _tmain name was irrelevant
2. Didn't know _tmain is a #define for main
3. Couldn't find the error causing the problem.
4. Didn't want to spend time finding the problem.
5. Wanted to post something, regardless it doesn't help.

If cases 1-3 hold, you were simply ignorant. If 4-5, you were
malicious. Certainly, you didn't help.

.... and you are a fool that can't read FAQ how to post questions in this
news group:
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8

This is what I got trying to compile OP's code:

g++ qqq.cpp -o qqq
qqq.cpp: In member function
‘virtual<unnamed>::Fraction&<unnamed>::Fraction::eek:perator=(const<unnamed>::Fraction&)’:
qqq.cpp:15: error: ‘cout’ was not declared in this scope
qqq.cpp: In member function
‘virtual<unnamed>::Fraction2&<unnamed>::Fraction2::eek:perator=(const<unnamed>::Fraction2&)’:
qqq.cpp:31: error: ‘cout’ was not declared in this scope
qqq.cpp: At global scope:
qqq.cpp:41: error: ‘_TCHAR’ has not been declared
qqq.cpp: In function ‘int _tmain(int, int**)’:
qqq.cpp:48: error: ‘system’ was not declared in this scope
 
J

James Kanze

When I say philosophy, I mean people usually don't do that,
because it is often a bad design (try to make operator=
polymiorphism), isn't it?

In general, polymophism and value semantics (copy and
assignment) don't go well together. Consider the following:

Base* p1 = new Derived1 ;
Base* p2 = new Derived2 ;
*p1 = *p2 ;

logically, you would expect *p1 and *p2 to be equal after that
(for some suitable definition of equal). But in fact, they will
still have different types; there's no way to dynamically change
the type of an object once it has been created. For this
reason, *most* polymorphic hierarchies will ban assignment (and
make copy private, so that it can only be used in a clone()
function, which creates a new instance).

If you really need value semantics and polymorphism, look up the
letter-envelop idiom. Most of the time, however, I think you'll
find that just using a pointer and/or references is
adequate---this is one case where boost::shared_ptr is often
appropriate.
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top