Question on this overload program

  • Thread starter Thread starter yungman
  • Start date Start date
  • Tags Tags
    Program
AI Thread Summary
The discussion centers around issues with a modified C++ overload program, particularly concerning memory management and string handling in a class. The main problem arises from the use of shallow copying in the copy constructor, leading to garbage values when accessing string data after object destruction. Participants suggest implementing deep copying to properly manage dynamic memory and recommend using `std::string` for better safety and ease of use, especially in modern C++ programming. The original poster expresses interest in understanding compiler behavior and the implications of their coding choices. Ultimately, the conversation highlights the importance of proper memory handling and the advantages of using standard library features over raw C-strings.
  • #51
Is physics forum going to condone V50 with all the spikeful remarks in this prestige forum? He is NOT helping except being spikeful. This is an education forum, he is obviously taking it very personal. Notice he putting LIKE on everything that is degrading to me? This is small...on his part. Get a life. You can band me, I'll find other ways to learn C++, I just want to point out the lack of life of him, Get a life, find something better to do! When I was on PF advising people on EE, if they are rude, I'd say it once and just put on ignore. I have better things to do in life.
 
Last edited:
Technology news on Phys.org
  • #52
yungman said:
Is physics forum going to condone V50 with all the spikeful remarks in this prestige forum? He is NOT helping except being spikeful.
V50 has two posts in this thread, neither of which was aimed at you or discussed you in any way.

BTW, the word is "spiteful."
yungman said:
Notice he putting LIKE on everything that is degrading to me?
The things that you view as being degrading to you are for the most part truthful comments about the way you approach this forum. I would agree that some of V50's comments in other threads were harsh, but for you to complain about posts in this thread that V50 agrees with and likes is pretty thin.

You come here to this forum to ask for help, and get tons of help. If we ask you to make it easier to help you by making your code easier to read, by reading our replies before launching into posts with questions we've already answered, it seems to me a more reasonable thing to do would be to help us out, not post baseless complaints.
 
  • #53
Mark44 said:
V50 has two posts in this thread, neither of which was aimed at you or discussed you in any way.

BTW, the word is "spiteful."
The things that you view as being degrading to you are for the most part truthful comments about the way you approach this forum. I would agree that some of V50's comments in other threads were harsh, but for you to complain about posts in this thread that V50 agrees with and likes is pretty thin.

You come here to this forum to ask for help, and get tons of help. If we ask you to make it easier to help you by making your code easier to read, by reading our replies before launching into posts with questions we've already answered, it seems to me a more reasonable thing to do would be to help us out, not post baseless complaints.
This is a long feud between me a V50. He needs to get a life instead of being spiteful. We are all old, just let it go.

The difference is he only mock and spite, he never helps. Like I said, I was on the other end not too long ago advising people, give it a rest to the beginners. Don't like it, don't respond. Don't spite people, get a life.
 
  • #54
@yungman, regarding the problem you were trying to solve when you opened this thread (adding a C-string name field to the class), here are some pieces of my solution. The code is based on what @jtbell posted.
The class definition, in what I'm calling ThreeV.h:
C++:
#include <iostream>
#include <cstring>

using std::cout; using std::endl;
using std::ostream;
const int SIZE = 25;

class ThreeVector
{
private:
    double x, y, z;
    char name[SIZE];
    int serialNum;          // unique for each ThreeVector instance
    static int numVectors;  // counts the number of ThreeVectors constructed
public:
    ThreeVector();                        // default constructor
    ThreeVector(double, double, double, const char*);
    ThreeVector(const char* name);
    ThreeVector(const ThreeVector&);      // copy constructor
    ~ThreeVector();
    ThreeVector operator+ (const ThreeVector&) const;
    ThreeVector& operator= (const ThreeVector&);
    friend ostream& operator<< (ostream& out, const ThreeVector& v);
};
A couple of the function definitions, in the same file:
C++:
// Default ctor
ThreeVector::ThreeVector()
{
    x = 0;  y = 0;  z = 0;
    strncpy_s(name, SIZE - 1, "Default", SIZE - 1);
    numVectors++;
    serialNum = numVectors;    
    cout << "-- Default-constructed vector #" << serialNum << endl;   
}
// Another ctor
ThreeVector::ThreeVector(double x0, double y0, double z0, const char * str) 
{
    x = x0;  y = y0;  z = z0;
    strncpy_s(name, SIZE-1, str, SIZE - 1);
    numVectors++;
    serialNum = numVectors;
    cout << "-- Constructed vector #" << serialNum << endl;     
}

// Overloaded operator+()
ThreeVector ThreeVector::operator+ (const ThreeVector& rhs) const
{
    ThreeVector sum("Sum");
    sum.x = x + rhs.x;  sum.y = y + rhs.y;  sum.z = z + rhs.z;
    //cout << "-- " << *this << " + " << rhs
    //    << " = " << sum << "." << endl;
    cout << "Return from operator+..." << endl;
    return sum;    
}
Not shown are
  • a constructor that initializes the name portion with a specified string, and initializes the other data members to 0
  • a copy constructor
  • the destructor (same as jtbell posted)
  • overloaded operator=()
  • overloaded operator<<() (same as jtbell posted)
The class consumer:
C++:
#include <iostream>
#include "ThreeV.h"
using std::cout; using std::endl;

int main()
{    
    cout << "Declare a and b..." << endl;
    ThreeVector a(1, 2, 3, "VecA"), b(4, 5, 6, "VecB");
    cout << "a: " << a << " b: " << b << endl;
    cout << "Declare c and add c = a + b..." << endl;
    ThreeVector c;
    ThreeVector d("VecD");
    cout << "c: " << c << " d: " << d << endl;
    c = a + b;
    cout << "c: " << c << endl;
    cout << "Return from main()..." << endl;    
}
 
  • #55
Hi Mark

I want to first apologize to you and the forum that my anger got the best of me yesterday and got you caught in the middle.

I did take a detour as I want to learn deeper into shallow copy and more on assignment operator. But I am back. I really want to catch up the posts I've missed since yesterday. Just want to make sure you know I am not MIA, I am back, give me some time to catch up with your suggestion and Jarvis323's first and work down the line.

Thanks for all your help. I'll be back.

Alan
 
  • #56
Mark44 said:
From post #31, Source.cpp:
C++:
// Cannot use overload =
    Result = First + Second;
Your comment above misses the point. The expression on the right of the assignment operator assumes that you have a valid operator+(), that returns a Vec object. You don't, since your implementation, shown below, returns void. IOW, your implementation doesn't return anything at all.

Since you haven't overloaded the + operator, the expression First + Second is a syntax error.

From the same post, Overload.h:
C++:
Vec sum() { x = 0; y = 0; strncpy_s(name, 25, sumName, 25); }//OK, declaring Vec sum.
.
.
.
void operator+ (const Vec& rhs) const//sum is public, no need to return
        { sum.x = x + rhs.x;  sum.y = y + rhs.y;} //Problem using sum
What's worse, you have a function member named sum(), but your operator+() seems to be using sum as if it were a Vec object. This is also wrong.
Thanks for the reply. I was trying to declare sum as an object of Vec not a member function. How can I do that in the class declaration?

My goal is to have a real object to use in the operator+() so it won't be destroyed upon exiting the function.

I tried
C++:
char sumName[25] = "sum";
Vec(){ name = sumName; x = 0; y = 0}// constructor with no argument
Vec sum();
It didn't work. So I tried the other way. Seems like I cannot declare an object inside the class definition.Thanks
 
  • #57
yungman said:
I was trying to declare sum as an object of Vec not a member function. How can I do that in the class declaration?
Look at the code of yours that I quoted, and that you just quoted. You have a function named sum that returns a Vec object and in your operator+() overload, you have some undeclared object named sum. You can't do that!
yungman said:
My goal is to have a real object to use in the operator+() so it won't be destroyed upon exiting the function.
Why? Look at the code I posted in post #54. I show an implementation of operator+() that works. That code creates a temporary object named sum, and returns it. Before it gets destroyed, the overloaded operator=() will assign the values in sum to whatever object is on the left side of the assignment.
 
  • Like
Likes yungman
  • #58
yungman said:
I tried
C++:
char sumName[25] = "sum";
Vec(){ name = sumName; x = 0; y = 0}// constructor with no argument
Vec sum();
It didn't work. So I tried the other way. Seems like I cannot declare an object inside the class definition.
Line 3 is wrong. When you create an object by calling the default constructor, you don't include the parentheses.
Look at the code I provided, in the part with main(). I didn't give you all the code, but you should be able to fill in the missing pieces and get the code in main() to run.
 
  • #59
Hi Mark
I copied your program in post
Mark44 said:
@yungman, regarding the problem you were trying to solve when you opened this thread (adding a C-string name field to the class), here are some pieces of my solution. The code is based on what @jtbell posted.
The class definition, in what I'm calling ThreeV.h:
C++:
#include <iostream>
#include <cstring>

using std::cout; using std::endl;
using std::ostream;
const int SIZE = 25;

class ThreeVector
{
private:
    double x, y, z;
    char name[SIZE];
    int serialNum;          // unique for each ThreeVector instance
    static int numVectors;  // counts the number of ThreeVectors constructed
public:
    ThreeVector();                        // default constructor
    ThreeVector(double, double, double, const char*);
    ThreeVector(const char* name);
    ThreeVector(const ThreeVector&);      // copy constructor
    ~ThreeVector();
    ThreeVector operator+ (const ThreeVector&) const;
    ThreeVector& operator= (const ThreeVector&);
    friend ostream& operator<< (ostream& out, const ThreeVector& v);
};
A couple of the function definitions, in the same file:
C++:
// Default ctor
ThreeVector::ThreeVector()
{
    x = 0;  y = 0;  z = 0;
    strncpy_s(name, SIZE - 1, "Default", SIZE - 1);
    numVectors++;
    serialNum = numVectors;
    cout << "-- Default-constructed vector #" << serialNum << endl;
}
// Another ctor
ThreeVector::ThreeVector(double x0, double y0, double z0, const char * str)
{
    x = x0;  y = y0;  z = z0;
    strncpy_s(name, SIZE-1, str, SIZE - 1);
    numVectors++;
    serialNum = numVectors;
    cout << "-- Constructed vector #" << serialNum << endl; 
}

// Overloaded operator+()
ThreeVector ThreeVector::operator+ (const ThreeVector& rhs) const
{
    ThreeVector sum("Sum");
    sum.x = x + rhs.x;  sum.y = y + rhs.y;  sum.z = z + rhs.z;
    //cout << "-- " << *this << " + " << rhs
    //    << " = " << sum << "." << endl;
    cout << "Return from operator+..." << endl;
    return sum;
}
Not shown are
  • a constructor that initializes the name portion with a specified string, and initializes the other data members to 0
  • a copy constructor
  • the destructor (same as jtbell posted)
  • overloaded operator=()
  • overloaded operator<<() (same as jtbell posted)
The class consumer:
C++:
#include <iostream>
#include "ThreeV.h"
using std::cout; using std::endl;

int main()
{
    cout << "Declare a and b..." << endl;
    ThreeVector a(1, 2, 3, "VecA"), b(4, 5, 6, "VecB");
    cout << "a: " << a << " b: " << b << endl;
    cout << "Declare c and add c = a + b..." << endl;
    ThreeVector c;
    ThreeVector d("VecD");
    cout << "c: " << c << " d: " << d << endl;
    c = a + b;
    cout << "c: " << c << endl;
    cout << "Return from main()..." << endl;
}
Hi Mark

Do you mean I just copy the ones in bold blue above straight from Jtbell's program with no change?

Also. For what ever reason passing c-string like ThreeVector a(1, 2, 3, "VecA") never works. I always have to:
C++:
char name[]="Alan";
ThreeVector a(1, 2, 3, name);
Don't ask me why, it always is! Is it because my VS is the free version?

Thanks
 
  • #60
yungman said:
For what ever reason passing c-string like ThreeVector a(1, 2, 3, "VecA") never works. I always have to:
C++:
char name[]="Alan";
ThreeVector a(1, 2, 3, name);
What is the code for that constructor? I don't see one that matches, in the code that you've previously posted in this thread. (Forgive me if I somehow managed to skip past it while scrolling through the three pages of this thread...)

Also, what error message did you get?
 
  • #61
yungman said:
Do you mean I just copy the ones in bold blue above straight from Jtbell's program with no change?
The two that are marked "same as jtbell's code" you can copy directly, but the other three, you need to add a few lines of code. If you look at the code for the member functions that I posted, you should be able to figure out what these three member functions need.
yungman said:
Also. For what ever reason passing c-string like ThreeVector a(1, 2, 3, "VecA") never works.
Because that's one of the constructors you need to implement.
Mark44 said:
Not shown are
  • a constructor that initializes the name portion with a specified string, and initializes the other data members to 0
 
Last edited:
  • #62
Mark44 said:
The two that are marked "same as jtbell's code" you can copy directly, but the other three, you need to add a few lines of code. If you look at the code for the member functions that I posted, you should be able to figure out what these three member functions need.

Because that's one of the constructors you need to implement.
No, that's not what I was asking, I am talking about you put in "VecA". It never worked on my VS, I have to put char cAr[]="VecA"; then ThreeVector a(1, 2, 3, cAr). That's the reason when you look at my program, I have to have all those c-string declarations.

Thanks
 
Last edited by a moderator:
  • #63
yungman said:
No, that's not what I was asking, I am talking about you put in "VecA". It never worked on my VS, I have to put char cAr[]="VecA"; then ThreeVector a(1, 2, 3, cAr). That's the reason when you look at my program, I have to have all those c-string declarations.
I showed the implementation for the constructor with three double arguments and a string, in post #54. If the class definition you use and the constructor I showed are exactly as I wrote them, it will work.
C++:
ThreeVector::ThreeVector(double x0, double y0, double z0, const char * str)
Are you missing const in the declaration of the string parameter?

In main, you can see this declaration for the a and b objects:
C++:
ThreeVector a(1, 2, 3, "VecA"), b(4, 5, 6, "VecB");
As you know, I'm also using VS.
 
Last edited:
  • Like
Likes yungman
  • #64
Mark44 said:
I showed the implementation for the constructor with three double arguments and a string, in post #54. If the class definition you use and the constructor I showed are exactly as I wrote them, it will work.
C++:
ThreeVector::ThreeVector(double x0, double y0, double z0, const char * str)
Are you missing const in the declaration of the string parameter?

In main, you can see this declaration for the a and b objects:
C++:
ThreeVector a(1, 2, 3, "VecA"), b(4, 5, 6, "VecB");
As you know, I'm also using VS.
You are right. I went back to play with c-string again in chapter 10. when I said it doesn't work it's because I did it wrong. This is what I did:
C++:
const int size = 25;
char name[size];
name[size] = "alan"; //Won't work.

strncpy_s(name, size, "alan", size);// this works, I just forgot I need strncpy_s().

I assume this will not work for a long time!

That's why I like this kind of playing with the program even though I have stop studying the book and put it on hold. This is where rubber hits the road, really test out how much I really understand this. I feel I learn a lot with this. If I just follow the book and don't step out, I'd miss all these and thought I understand.

Sadly, this is how it is in school. You want to bet I would get a high "A" if I am taking the class. Just because one can get the right code doesn't mean they understand what they are doing. You are a professor, you must see a lot of this. That's why I always stop and have a reality check even most here said I am wasting my time. Books and even in class, they can only show you one or two examples. You understand those and you think you understand. But in real world there is so many different variations.

Right now, I am looking at when to use Vec& operation xx ( ), when to use Vec operation xx () when to declare void with no return. Book only show one example, but in real world, you can have all variations.

Then book never even talked about how compiler works, thread from Jtbell show there are steps in between lines of code. It's important to know a little how the compiler thinks. You guys think it's common sense, believe me, It is NOT.

Thank
 
Last edited:
  • #65
Hi Mark
I have issue with even the very beginning with your program, it's is about the c-string name[size]. I put it in a very short program to show you.
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int size;
class Vec
{private:
    int x, y, z;
    char name[size];
public:
};
Error.jpg


I have encountered this many times before. Another example that I tried:
Error1.jpg


There is something different when putting this in the class declaration vs in normal main(). I tried putting in private, public and all, nothing works. Thta's the reason I use name = new char[size] in my post 1 here. That's the only way so far that works.This is also the same question I kept asking, why can't I declare Vec sum to create object sum in the class declaration. I know I can do that in main().

I am missing something.

Thanks
 
  • #66
yungman said:
#include <iostream> #include <cstring> using namespace std; const int size;
In this example (the first one), you have to give size a value.
yungman said:
This is also the same question I kept asking, why can't I declare Vec sum to create object sum in the class declaration. I know I can do that in main().
In main() you use one of the constructors to create an object, but it doesn't make any sense to me to have a data member of a class be the same type that the class is declaring.

C++:
class Foo
{
private:
    int x, y, z;
    Foo obj; 
public:
    <member functions>
};
Do you see what I'm getting at?

Of course, the implementations of the member functions can have class objects as parameters, return types, or temp variables, and the code that jtbell provided shows this, as does the variant of his code that I've provided.
 
  • #67
yungman said:
I have encountered this many times before. Another example that I tried:
Your headers for two of the constructors have a parameter of type char *. They should be const char *.

Instead of fiddling around with your old code, you'd be better off working with the code I showed in post #54, and filling in what I didn't provide.
 
  • Like
Likes Vanadium 50
  • #68
Mark44 said:
In this example (the first one), you have to give size a value.
In main() you use one of the constructors to create an object, but it doesn't make any sense to me to have a data member of a class be the same type that the class is declaring.

C++:
class Foo
{
private:
    int x, y, z;
    Foo obj;
public:
    <member functions>
};
Do you see what I'm getting at?

Of course, the implementations of the member functions can have class objects as parameters, return types, or temp variables, and the code that jtbell provided shows this, as does the variant of his code that I've provided.
I somehow deleted the 25. It's the same thing after I put it back in as shown:
Error.jpg

Did you see my second example that I screen capture all the red wiggle on the "size". It's the same problem. I had const int size = 25 in that program. this never work. So I need to fix this part of your program before I can go any further because that's what you have also.

On the second question, so I cannot declare Vec sum inside Vec class declaration?

I am looking at your code, it doesn't seem to me that it's better than my very first post. My original question was why object Temp has garbage in the name and passed back into Result. I would expect "sum".
Both the Assignment operator() and Copy Constructor in your program do NOT pass the name over, that's the reason the original name is preserved. In my program, I actually tried to print out the name in Temp and pass the name to Result, that's why I got the garbage.

I need to look more into your program, but first pass, I don't think it help me in my case. Like my very first program, if I eliminate the printout of Temp and don't pass the garbage, everything will look just fine and end of story.

Thanks
 
  • #69
yungman said:
I am looking at your code, it doesn't seem to me that it's better than my very first post.
Sure it is -- it compiles without error and it runs and produces correct results.

Here's from my class definition:
C++:
#include <iostream>
#include <cstring>

using std::cout; using std::endl;
using std::ostream;
const int SIZE = 25;

class ThreeVector
{
private:
    double x, y, z;
    char name[SIZE];
    int serialNum;          // unique for each ThreeVector instance
    static int numVectors;  // counts the number of ThreeVectors constructed
... <public members>

A possible reason for the problem you're seeing is that you have using namespace std;
I said a long time ago that bringing the whole namespace in like this is a bad idea. It seems very likely to me that the std namespace has a definition for something called size, and the compiler can't tell which one you mean: the size in the std namespace or the size that you have defined.
 
  • Love
Likes Vanadium 50
  • #70
Mark44 said:
It seems very likely to me that the std namespace has a definition for something called size, and the compiler can't tell which one you mean: the size in the std namespace or the size that you have defined.
And sure enough, that is the case. size is defined in no fewer than 14 headers, including <vector>, <string>, <array>, and others.
 
  • Like
Likes yungman
  • #71
Mark44 said:
. It seems very likely to me that the std namespace has a definition for something called size, and the compiler can't tell which one you mean: the size in the std namespace or the size that you have defined.

You are correct.
 
  • #72
Mark44 said:
Sure it is -- it compiles without error and it runs and produces correct results.

Here's from my class definition:
C++:
#include <iostream>
#include <cstring>

using std::cout; using std::endl;
using std::ostream;
const int SIZE = 25;

class ThreeVector
{
private:
    double x, y, z;
    char name[SIZE];
    int serialNum;          // unique for each ThreeVector instance
    static int numVectors;  // counts the number of ThreeVectors constructed
... <public members>

A possible reason for the problem you're seeing is that you have using namespace std;
I said a long time ago that bringing the whole namespace in like this is a bad idea. It seems very likely to me that the std namespace has a definition for something called size, and the compiler can't tell which one you mean: the size in the std namespace or the size that you have defined.
Oh my god, you are correct. I never thought about that. Now I can at least move on. Never thought namespace std caused so much problem.

Thanks a million.
 
  • #73
yungman said:
really test out how much I really understand this.
Here's a test:

Q1. Explain using the terms 'declaration' (or declare) and 'initialisation' (or initialise) why this code does not make sense:
C++:
const int size;

Q2. `Give 2 reasons why this code doesn't work:
C++:
char name[25];
name[25] = "alan";

Mark44 said:
yungman said:
I am looking at your code, it doesn't seem to me that it's better than my very first post.
Sure it is -- it compiles without error and it runs and produces correct results.
Made my day :DD.
 
  • Like
Likes Mark44
  • #74
Mark44 said:
I said a long time ago that bringing the whole namespace in like this is a bad idea.

Yes you did. However, I think there are degrees of badness:

C++:
#include<iostream>
using namespace std;
int main() {
   cout << "Test.\n";
   return(0);
}

is very bad, because it infects everything.

C++:
#include<iostream>
int main() {
   using namespace std;
   cout << "Test.\n";
   return(0);
}

is better, because it only infects main(). In a subroutine, this is better. In a member function, better still.

C++:
#include<iostream>
int main() {
   using std::cout;
   cout << "Test.\n";
   return(0);
}

is even better still, because it brings in only the one needed element, so the odds of a collision go way down.
 
  • #75
pbuk said:
Here's a test:

Q1. Explain using the terms 'declaration' (or declare) and 'initialisation' (or initialise) why this code does not make sense:
C++:
const int size;

Q2. `Give 2 reasons why this code doesn't work:
C++:
char name[25];
name[25] = "alan";
Made my day :DD.
First question, it was a mistake, somehow I deleted it when I copied over.
Second is easy, I just learn it today. Need to use strncpy_s(name, 25, "alan", 25).
 
  • #76
pbuk said:
Q2. `Give 2 reasons why this code doesn't work:
C++:
char name[25];
name[25] = "alan";
yungman said:
Second is easy, I just learn it today. Need to use strncpy_s(name, 25, "alan", 25).
No, you didn't answer what @pbuk asked you to do, which was to give 2 reasons why that code doesn't work. He didn't ask you to do it another way.
 
  • Like
Likes Vanadium 50
  • #77
Mark44 said:
No, you didn't answer what @pbuk asked you to do, which was to give 2 reasons why that code doesn't work. He didn't ask you to do it another way.
Yes I did! First one I forgot the 25. the second one is using the wrong =, can't do that with c-strings. Isn't that obvious?
 
  • #78
You can define your const int size = 25 inside the class, as member data, but you have to make it static, presumably because that value is intended to be shared among all the instances of the class.
C++:
class Vec
{private:
    int x, y, z;
    static const int size = 25;
    char name[size];
// etc.
};
Hmmm... when I try to make it non-static (const int size = 25;), g++ gives me merely a warning message, not an error: in-class initialization of non-static data member is a C++11 extension.

Which version of C++ does VS default to? It might depend on which version of VS you're using.
 
  • Like
Likes yungman
  • #79
jtbell said:
You can define your const int size = 25 inside the class, as member data, but you have to make it static, presumably because that value is intended to be shared among all the instances of the class.
C++:
class Vec
{private:
    int x, y, z;
    static const int size = 25;
    char name[size];
// etc.
};
Hmmm... when I try to make it non-static (const int size = 25;), g++ gives me merely a warning message, not an error: in-class initialization of non-static data member is a C++11 extension.

Which version of C++ does VS default to? It might depend on which version of VS you're using.
I am glad you are here. This is an extension YOUR thread! I just don't want to hijack your thread so I started my own. My VS is 2019.

To me, your thread was quite clear on what steps the compiler was doing. I carried on one step more, I want to look when I give a c-string to the class, I want to see how it is being copied. I am not convinced at all that there is a solution to copy the c-string over yet. In the very first post, I showed the name is not passed from what you called Vector#4(sum) to Vector#5(some temporary). There is a miss connection there and I got garbage when I print out the c-string of Result( which is your c).

About the "size", this has been resolved thanks to Mark. I just don't use using namespace std. Or maybe changing the name size.

Thanks
 
Last edited:
  • #80
Apparently I still running into issue of passing c-string as parameter. Here is the very short program and you can see one way works and the other doesn't:
C++:
#include <iostream>
#include <cstring>
using std::ostream;
using std::cout; using std::endl;
const int size = 25;
class Vec
{private:
    int x, y;
    char name[size];
public:
    Vec(int x0, int y0, char *desc)
        { x = x0, y = y0;
          strncpy_s(name, size, desc, size);        
        }
};
int main()
{    char vecA[size] = "vecA";
    Vec a(1, 2, vecA);//This works
    Vec b(2, 4, "vecB");//This doesn't work.
    return 0;
}
Error.jpg

Line 20 just won't work. Why?

Thanks
 
  • #81
yungman said:
Line 20 just won't work. Why?
Already answered. See post #67. Again, please read what others and I write. It's disrespectful to us and wasteful of our time when we answer a question that you've asked, and you don't read the responses, and ask the same question again.

No, you still didn't answer what @pbuk asked you to do, which was to give 2 reasons why the code below doesn't work.
C++:
char name[25];
name[25] = "alan";

yungman said:
the second one is using the wrong =, can't do that with c-strings. Isn't that obvious?
If that's the wrong =, is there another = that works? What's your second reason?
 
  • #82
yungman said:
Line 20 just won't work. Why?
Mark44 said:
See post #67.
To elaborate a bit on the statement in post #67:

A literal string such as "vecB" doesn't have type char *. It implicitly has type const char *, because it makes no sense to change the value of a literal string.

You can't pass a const char * to a function that declares a parameter to be char *. When you declare a parameter without specifying const, it signals to the compiler that the function might change the value of the parameter.

Therefore, if you want to be able to pass a literal string to a function, you must declare the parameter as const char *.

(On the other hand, you can pass a char * (e.g. a char array that isn't declared as const) to a function that declares a parameter as const char *.)

[oops, yungman quoted this while I was editing it for clarity.]
 
Last edited:
  • Like
Likes yungman
  • #83
jtbell said:
To elaborate a bit on the statement in post #67:

A literal string such as "vecB" doesn't have type char *. It has type const char *.

You can't pass a const char * to a function that declares a parameter to be char *. When you declare a parameter without specifying const, it signals to the compiler that the function might change the value of the parameter. However, it makes no sense to change the value of a literal string, so those are always implicitly const char *.

(On the other hand, you can pass a char * (e.g. a char array that isn't declared as const) to a function that declares a parameter as const char *.)
THANK YOU
This is what I need. I have not seen any explanation on this before. That's why I make mistake and don't even know why. Whole day today has been tripped by the c-string copying and passing parameter. this definitely will be in my notes.

that's why when I read Marks reply again, I still didn't understand until your post just pop up! Just like in your thread, everyone replied sounded like they think everyone knew all that, that was NEW to me, that was an eye opener! That's why I spent over a week now on your post and I refuse to move on until I get everything to learn out of it.

Actually I am in the process of writing out the program without looking at any of the stuff, line by line reasoning out, step by step doing it again.

Thanks
 
  • #84
You might want to check the revised version of my post. I was in the middle of editing it when you quoted it. I didn't change the main point, just tried to make it clearer (hopefully).
 
  • #85
jtbell said:
You might want to check the revised version of my post. I was in the middle of editing it when you quoted it. I didn't change the main point, just tried to make it clearer (hopefully).
Can you tell me which post #?

thanks
 
  • #86
yungman said:
Actually I am in the process of writing out the program without looking at any of the stuff
Please stop!
Read through this thread before you start writing out the program. At the very least, doing so might eliminate more questions that we've already answered.
 
  • Like
Likes Vanadium 50
  • #87
I did it. My biggest road block is about the passing and copying c-string. After learning all those today thanks to Mark and Jtbell, it is very smooth to write my own. I wrote the whole program with very little peeking to the existing programs. It is actually different enough from Jtbell's. I think I understand Jtbell's thread, I am ADDING to the program and remove some of the stuffs like the Vector# and z. I am concentrating on passing the c-string around and make sure it's not shallow copying. I did it!

I actually think about what I was writing to write the code, why I put const in front of the variable types like const char*. I got it done quite fast. this is my program:
C++:
#include <iostream>
#include <cstring>
using std::ostream;
using std::cout; using std::endl;
const int size = 25;
class Vec
{private:
    int x, y;
    char name[size];
public:
    Vec(){ x = 0, y = 0;
        strncpy_s(name, size, "Default", size);
        cout << " [In Dconstructor], object created: " << name <<
            "(" << x << "," << y << ")   address: " << this << "\n\n";
    }
    Vec(const char*desc) { x = 0, y = 0;
         strncpy_s(name, size, desc, size);
         cout << " [In Constructor], object created: " << name <<
         "(" << x << "," << y << ")   address: " << this << "\n\n";
        }
    Vec(int x0, int y0, const char *desc){ x = x0, y = y0;
         strncpy_s(name, size, desc, size);
         cout << " [In Constructor], object created: " << name <<
             "(" << x << "," << y << ")   address: " << this << "\n\n";
        }
    Vec(const Vec& original)
      {    x = original.x; y = original.y;
        strncpy_s(name, size, "Temp", size);
        cout << " [In Copy Constructor], object created: " << name <<
            "(" << x << "," << y << ")   address: " << this << "\n\n";
      }
    ~Vec(){cout<<" Destroying "<<(*this).name<<",   Address: "<<this<<"\n\n";}
    Vec operator+(const Vec& right)
      {  Vec sum;
         sum.x = x + right.x; sum.y = y + right.y;
         strncpy_s(sum.name, size, "sum", size);
         cout <<" [In OP+]: " << sum.name << "(" << sum.x << "," << sum.y <<
             ") = " << (*this).name <<"(" << (*this).x << "," << (*this).y <<
             ") + " << right.name <<"(" << right.x << "," << right.y << ")\n\n";
         return sum;
      }
    Vec& operator=(const Vec& rhs)
      {x = rhs.x; y = rhs.y;
       strncpy_s(name, size, rhs.name, size);
       cout << " [In OP=]: " << rhs.name << "(" << rhs.x << "," << rhs.y <<
           ")   is copied into   " << name << "(" << x << "," << y << ")\n\n ";
       return *this;
      }
    friend ostream& operator<<(ostream& out, const Vec& v)
      {out << " [OP<<] c contains: " << v.name << "(" << v.x << "," << v.y << ")\n\n"; return out; }
};

int main()
{    Vec a(1, 2, "vecA");
    Vec b(3, 4, "vecB");
    Vec c("vecC");
    c = a + b;
    cout << c << "\n\n";
    return 0;
}
Attached is the print out. I checked the address where the compiler go step by step.
I intentionally let "Temp" to copy over to object c so when I display c, I get Temp(4,6). This is by intention to show I successfully pass the literal c-string in every step.

Thanks everyone for the help. I am going to look at Mark's program and make it work tomorrow. I learn so much out of this exercise, it's a week of hard work worth while. I don't think I can do nearing half if I stick to the book. Now I feel good about the overloading operator a lot better than last week.

Thanks a million to everyone that helped me.
 

Attachments

  • #88
Mark44 said:
@yungman, regarding the problem you were trying to solve when you opened this thread (adding a C-string name field to the class), here are some pieces of my solution. The code is based on what @jtbell posted.
The class definition, in what I'm calling ThreeV.h:
C++:
#include <iostream>
#include <cstring>

using std::cout; using std::endl;
using std::ostream;
const int SIZE = 25;

class ThreeVector
{
private:
    double x, y, z;
    char name[SIZE];
    int serialNum;          // unique for each ThreeVector instance
    static int numVectors;  // counts the number of ThreeVectors constructed
public:
    ThreeVector();                        // default constructor
    ThreeVector(double, double, double, const char*);
    ThreeVector(const char* name);
    ThreeVector(const ThreeVector&);      // copy constructor
    ~ThreeVector();
    ThreeVector operator+ (const ThreeVector&) const;
    ThreeVector& operator= (const ThreeVector&);
    friend ostream& operator<< (ostream& out, const ThreeVector& v);
};
A couple of the function definitions, in the same file:
C++:
// Default ctor
ThreeVector::ThreeVector()
{
    x = 0;  y = 0;  z = 0;
    strncpy_s(name, SIZE - 1, "Default", SIZE - 1);
    numVectors++;
    serialNum = numVectors;  
    cout << "-- Default-constructed vector #" << serialNum << endl; 
}
// Another ctor
ThreeVector::ThreeVector(double x0, double y0, double z0, const char * str)
{
    x = x0;  y = y0;  z = z0;
    strncpy_s(name, SIZE-1, str, SIZE - 1);
    numVectors++;
    serialNum = numVectors;
    cout << "-- Constructed vector #" << serialNum << endl;   
}

// Overloaded operator+()
ThreeVector ThreeVector::operator+ (const ThreeVector& rhs) const
{
    ThreeVector sum("Sum");
    sum.x = x + rhs.x;  sum.y = y + rhs.y;  sum.z = z + rhs.z;
    cout << "Return from operator+..." << endl;
    return sum;  
}
Not shown are
  • a constructor that initializes the name portion with a specified string, and initializes the other data members to 0
  • a copy constructor
  • the destructor (same as jtbell posted)
  • overloaded operator=()
  • overloaded operator<<() (same as jtbell posted)
The class consumer:
C++:
#include <iostream>
#include "ThreeV.h"
using std::cout; using std::endl;

int main()
{  
    cout << "Declare a and b..." << endl;
    ThreeVector a(1, 2, 3, "VecA"), b(4, 5, 6, "VecB");
    cout << "a: " << a << " b: " << b << endl;
    cout << "Declare c and add c = a + b..." << endl;
    ThreeVector c;
    ThreeVector d("VecD");
    cout << "c: " << c << " d: " << d << endl;
    c = a + b;
    cout << "c: " << c << endl;
    cout << "Return from main()..." << endl;  
}
Hi Mark

I look through your program one more time. I hope I don't offend you, I think you missed my point from my first post. I have no problem printing out name of a, b and c( in your program is vecA, vecB and vecC) right from the beginning. If you look at my first post and the print out, you would see I got those already. My issue is the name in Temp got lost when copy from sum to Temp and thereby getting garbage in the final Result(which is vecC in your program).

You only provided the part that I already did in my very first post by constructors with names. ( I use name = new char[]). My question are ALL in Copy Constructor and operator=() which you have not addressed. That's what I was working on through out the whole thread here. that's why when you ask me to work with your program, I already kind of know that's not it already.

But I thank you for getting me through the issue of copying c-string and passing c-string as parameter using const char*desc. It turn out that's all the problem with me. After I understand from you and Jtbell, I have no issue writing the program one time through tonight. Now I proof I can write program with these few operators and constructors.

If you look at my final program, I actually copy the name from sum and change to Temp, then actually overwrite vecC to Temp in c step by step. When I print out c, I actually get Temp to proof I actually passing the c-string name over. It doesn't make sense, BUT that's what I set out to do in the very first post. This conclude my questions in this thread.

Thanks you so much for your help and patience. This thread is so important for me to understand deeper into overloading and more importantly, learn to look at how the compiler think.

Thanks
 
  • #89
yungman said:
Can you tell me which post #?

thanks
The one you were replying to... #82.
 
  • Like
Likes yungman
  • #90
jtbell said:
The one you were replying to... #82.
Oh good!, I need to edit my notes, I literally copy part of your post 82 into my notes. I thought you were talking about in your thread.

Thanks
 
Back
Top