Question on this overload program

  • Thread starter yungman
  • Start date
  • Tags
    Program
In summary: This variable goes out of scope after the constructor finishes, so the address becomes invalid. That's why when you try to print out the name in operator+(), you get garbage.To fix this, you should allocate memory for the "name" variable using the "new" keyword, similar to what you are doing in the other constructors. This will ensure that the variable's address remains valid even after the constructor finishes.In summary, the issue with the garbage output is due to assigning the address of a local variable to a member variable. To fix this, you should allocate memory for the variable using the "new" keyword. This will ensure
  • #36
Jarvis323 said:
And you can use std::string as a helper, to make life easier if you want,

C:
Vec operator+ (const Vec& rhs) const {
return Vec(( std::string( name ) + " + " + std::string( rhs.name ) ).c_str() ,x + rhs.x,y + rhs.y );
}

Note it is returning a Vec by value, which is crucial. You wouldn't want to return a temporary object by address/reference for reasons already explained.

I know you guys are trying to help yungman as he goes in strange directions, but advice him to mix std::string and C-strings is in my opinion a good example of showing him how C++ happily let's people shoot themself in the foot if they really want to. The c_str() from the above expression is going to be a dangling pointer no matter what context you use it in.

I will repeat my recommendation to yungman: If you want to learn modern C++ then use the modern "safe" API's, like the standard library, instead of trying to visit every anti-pattern and trap that the C-style API's has to offer. Shooting yourself in the foot over and over is of course one kind of lesson, but since a workable and clean approach for C++ programs do exists, why not take that instead.
 
Technology news on Phys.org
  • #37
Filip Larsen said:
The c_str() from the above expression is going to be a dangling pointer no matter what context you use it in.
I don't think so. I think that the temporary ( std::string( name ) + " + " + std::string( rhs.name ) ) is destroyed at the end of the expression it's part of. That occurs after the constructor it is an argument to returns.

https://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c

since a workable and clean approach for C++ programs do exists, why not take that instead.

Which is the workable c++ approach though if he wants to have all of the data held by his struct be contiguous in memory? He could use std::array< char, N >, but really that's essentially the same thing as char [N]. Personally my preference would be to use string everywhere (including in the arguments) except exactly where it comes to being stored in the struct. Of course you should probably never try to retain the pointer inside a string beyond the expression it's used in though.

For example,

C:
Vec( const std::string & desc, double x0, double y0)
{
    x = x0;  
    y = y0;
    strncpy_s( name, 25, desc.c_str(), 25 );
}
 
Last edited:
  • #38
Jarvis323 said:
I don't think so. I think that the temporary ( std::string( name ) + " + " + std::string( rhs.name ) ) is destroyed at the end of the expression it's part of. That occurs after the constructor it is an argument to returns. In general it is fine to pass a temporary object as a const reference or pointer

I cannot disagree with that. Your post just just (re)triggered a general opinion I have on the matter.

My comment was based on the assumption that c-string was being used as is and not copied over to a new buffer as it is in this specific case. But this also my point. In general such constructions are like small bombs you place in your program ready to go off if you change one part that will break the assumptions of another part. I understand the needs and trade-offs for doing this when experienced people know what they do and they can encapsulate such assumptions (like hidden as implementation detail in a class, as could be argued is the case here), but if a novice programmer should know about this it is should be to have the pattern on his dont-use-this list and not as a tool in his toolbox.

I know I am repeating myself, but you can learn to build skyscrapers the easy way by looking at design and procedures that is known to work good, or you can do it the hard way by repeating all the mistakes until, one day perhaps, your building finally stands without collapsing. Or in other words, the way forwards should be learning good patterns in general and then occasional anti-pattern to know what to stay away from and why.

Edit: fixed silly wording.
 
Last edited:
  • Like
Likes Jarvis323
  • #39
Filip Larsen said:
I cannot disagree with that. Your post just (re)triggered a general opinion I have on the matter.

My comment was based on the assumption that c-string was being used it is and not copied over as is the case for the constructor in this case. But this also my point. In general such constructions are like small bombs you place in your program ready to go off if you change one part that will break the assumptions of another part. I understand the needs and trade-offs for doing this when experienced people know what they do and they can encapsulate such assumptions (like hidden as implementation detail in a class, as could be argued is the case here), but if a novice programmer should know about this it is should be to have the pattern on his dont-use-this list and not as a tool in his toolbox.

I know I am repeating myself, but you can learn to build skyscrapers the easy way by looking at design and procedures that is known to work good, or you can do it the hard way by repeating all the mistakes until, one day perhaps, your building finally stands without collapsing. Or in other words, the way forwards should be learning good patterns in general and then occasional anti-pattern to know what to stay away from and why.
I agree with you, especially about the part where knowing the hidden implementation or standard details is necessary to know if it is safe or not. I guess code should be obviously safe just by looking at.
 
  • #40
Filip Larsen said:
but advice him to mix std::string and C-strings is in my opinion a good example of showing him how C++ happily let's people shoot themself in the foot if they really want to.

I agree that, except in rare instances, one should not mix C and C++ strings. It adds confusion and potential for error with little benefit. However, to be fair, this advice has been given before and rejected by the OP. The people who are trying to help are doing the best they can.

Jarvis323 said:
Which is the workable c++ approach though if he wants to have all of the data held by his struct be contiguous in memory?

Why would one want that? To be less flip, you seem to be describing a desire to have an array of variable and mutable length elements in contiguous and unfragmented memory. That is a hard and expensive thing to do. It's seldom necessary.
 
  • #41
Vanadium 50 said:
I agree that, except in rare instances, one should not mix C and C++ strings. It adds confusion and potential for error with little benefit. However, to be fair, this advice has been given before and rejected by the OP. The people who are trying to help are doing the best they can.
Why would one want that? To be less flip, you seem to be describing a desire to have an array of variable and mutable length elements in contiguous and unfragmented memory. That is a hard and expensive thing to do. It's seldom necessary.
One advantage is that you can read and write to and from disk much faster, and simpler. Or maybe you're using a gpu and need to move data to and from it, or maybe you are using mpi and moving data between processes.

The fact c and c++ guarantee contiguity of fields in a struct, in the order they are declared, is a pretty useful thing, especially for a vec.

That said a vec class with a string in it is also usually a bad idea as I mentioned. But maybe you have small strings you want associated with the vectors as some sort of categorical data, like a protein or something.

In yungman's case, I think he is still not ready to try binary IO with heap allocated and variable size data inside a class, as it would be more complicated to manage than anything he's done yet. And I knew he is going to want to do IO, like he did in the past, and I predicted he would run into a bunch of problems with that. So for him I think my recommendation will make his life easiest and prevent him from shooting himself in the foot a whole lot in the near future.

I also just thought, no matter if he should use an array in a class rather than a string, he should know the difference in terms of memory.
 
Last edited:
  • #42
Filip Larsen said:
I will repeat my recommendation to yungman: If you want to learn modern C++ then use the modern "safe" API's, like the standard library, instead of trying to visit every anti-pattern and trap that the C-style API's has to offer. Shooting yourself in the foot over and over is of course one kind of lesson, but since a workable and clean approach for C++ programs do exists, why not take that instead.
I can see where yungman is coming from, because I have a copy of the book he's using: Gaddis, Starting Out with C++, 6th ed. (2010). He provided a link to a PDF in a previous post in some other thread. Even though it's dated 12 years after the C++98 standard, it's still very "old-fashioned" in its treatment of std::string versus C-strings, and std::vector versus C-style arrays.

For example, it starts chapter 10 by introducing C-strings, and spends most of the chapter using them. The last section of the chapter introduces std::string. In later chapters, he always uses C-strings, as far as I can tell. The material on std::string was obviously "tacked onto" an earlier edition of the book. Chapter 7 handles C-style arrays and std::vector similarly.

Unfortunately, I don't know a more modern textbook to suggest (*), that is, a real textbook intended for college/university introductory programming courses. I stopped teaching such a course around 2005, when I had to give it up to another person in my department. He switched the course to Java, because that was the trend in the US at that time. I suspect there isn't much demand for C++ textbooks for such courses any more.

Gaddis's book is now in its 9th edition. The table of contents that I can see at the publisher's website looks pretty much the same, which suggests that its treatment of std::string and std::vector is the same, unfortunately.

(*) except for the book that I used in my course, which is long out of print, but which is now freely available from the author, as I've posted elsewhere.
 
  • Informative
Likes Jarvis323
  • #43
Jarvis323 said:
The stack is where memory is allocated for the local variables in a function. When a function is called, the stack is created to make that space, and when the function returns, the stack destroyed. So anything on the stack exists only inside of that function when it is called until it returns.
I disagree with part of the above. The stack is neither created nor destroyed. When a program starts up, it has its own chunk of stack storage to work with, as well as its own chunk of heap storage. When a function is called, space is allocated on the stack for local variables and function parameters. When the function returns to its caller, that stack space is reclaimed for possible later use by other functions or the OS.
 
  • Like
Likes Jarvis323
  • #44
I just want to give a quick reply to acknowledge everyone. I am just barely get to Jarvis323 post 32. It will take me a while to go and try out the suggestions one by one and ask question as this is important. I don't want to seem rude ignoring all your hard work posting.

This is how I feel I'm learning, none of these are in the book, the book only show one example of each, the scope is very limited, looking at different ways of doing things is a good learning process even though it turns out it shouldn't be done that way. So I am taking my time on this even if I have to stretch chapter 14 beyond Christmas.

Like I experimented in post 31 declaring sum outside the operator+(), it is NOT the usual way. BUT according to P825 of Gaddis's book, you can totally change the inside of a operator function:
P825.jpg


I declared sum inside the header file separately. But I got error when I put sum.x = x + rhs.x inside operation+(). I should be able to do that EVEN it is not the best way. Why the compiler gave me an error? It's not that I insist to do it my way, I want to know why. I think this is very important to know even though that's NOT the right way to do. I would like to find out why. I am sure I'll run into this kind of things in the future. My thinking was if I declare sum outside operator+(), it will NOT be destroyed when exiting the function. I still think that is one way of "deep" copying in a twisted sense!

Almost all the things in this thread is not talked about in the book, the book only show one way of doing things. I find this is very educational. Let me get back to jarvis323's post 32.

I'll be back.

Thanks.
 
Last edited:
  • #45
Jarvis323 said:
One advantage is that you can read and write to and from disk much faster, and simpler

My preference here is transient-persistent separation: the way you write data might be different from how you use it. You can do a lot of processing while the CPU is waiting for the data to rotate its way under the disk read head. Also, my experience is that there is more to be gained by storing less data than packing it more efficiently.

My data is all transparently compressed by the files system by LZ4/ Padding space between objects with nulls is no big deal - they will be (largely) compressed away so there is little penalty for them.
 
  • #46
Vanadium 50 said:
My preference here is transient-persistent separation: the way you write data might be different from how you use it. You can do a lot of processing while the CPU is waiting for the data to rotate its way under the disk read head. Also, my experience is that there is more to be gained by storing less data than packing it more efficiently.

My data is all transparently compressed by the files system by LZ4/ Padding space between objects with nulls is no big deal - they will be (largely) compressed away so there is little penalty for them.
In my case, I am doing distributed computing with MPI on 3d multivariate data. I need to do things like have each process load one chunk of the data, and also in parallel write it's result so that the results from all processes are combined into one file. And sometimes the layout of the chunk of data to read or write is not contiguous inside memory for each process, but is structured regularly. For this I use MPI_IO collective read and write operations with custom file views, that require you have some regular structure, because you specify how the process writes it's part based on offsets and sizes and stuff like that. Then also the data is huge, and IO is sometimes the bottleneck, so IO performance is critical. And then once the data is read, it's copied onto gpu's, using cudaMemcpy, for example. If I have a struct or class which doesn't allocate heap memory, then everything I described is perfectly fine. But if I had an std::string mixed in, then I would have a major headache. That said, the data has always been numerical.
 
  • #47
yungman said:
just want to give a quick reply to acknowledge everyone. I am just barely get to Jarvis323 post 32.
Before you post a response it would be a good idea to read all of the responses by other members, and not just stop at some post 10 or 15 posts back. That way you might not have to post a question that has already been answered.
yungman said:
BUT according to P825 of Gaddis's book, you can totally change the inside of a operator function:
And he says, "it is not a good programming practice." Just because the language allows you to do something, doesn't mean it's a good thing to do.
yungman said:
I declared sum inside the header file separately. But I got error when I put sum.x = x + rhs.x inside operation+().
There's an explanation in post #33. It's frustrating for many of us when you don't read or skip over some posts, and then ask a question that has already been answered.
 
  • Like
Likes Vanadium 50
  • #48
Also, you don't have to use my suggestion, instead as others have suggested, you are probably better off just using std::strings, and just move on rather than get hung up in this c-style stuff.
 
  • #49
Mark44 said:
Before you post a response it would be a good idea to read all of the responses by other members, and not just stop at some post 10 or 15 posts back. That way you might not have to post a question that has already been answered.
And he says, "it is not a good programming practice." Just because the language allows you to do something, doesn't mean it's a good thing to do.
There's an explanation in post #33. It's frustrating for many of us when you don't read or skip over some posts, and then ask a question that has already been answered.
Too many new stuffs here, I just had to stop and asked about initialization list before I can move on. Do you know if I don't understand things in a few consecutive post, reading on blindly is a waste of time. I thought I am being courteous to come back and said I'll get to it instead of letting everyone spent their time posting and I am MIA! This is no win. It might be very obvious to expert like you, for me, I have been grasping for air and try to keep my head above water right now.

I am trying to learn as much on my own I was watching a good video on assignment operator and Copy Constructor, the initialization lists stuff came up and I had to stop and search as I won't be able to follow if I don't understand it. These are NOT in the book.
 
Last edited:
  • #50
yungman said:
Do you know if I don't understand things in a few consecutive post, reading on blindly is a waste of time.
It's a waste of our time if you don't read what we have already written, and then ask a question that was answered in a post you didn't read or skipped over. I wouldn't have brought it up if the same thing had not happened several times.
At the very least, you could scan through the responses and see if someone has answered a question that you are about to ask. It's not necessary that you understand everything others have written on the first pass through it. You can always go back through the responses again, and focus more deeply on what you don't understand.
 
  • Like
Likes Vanadium 50
  • #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:
  • #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
Back
Top