Efficient C++ String Manipulation: Tips and Tricks from Experts

  • C/C++
  • Thread starter yungman
  • Start date
  • Tags
    C++ Strings
In summary: St1;The name stored in memory is: TestThe name stored in memory is: TesterThe name stored in memory is: Tester123
  • #71
jtbell said:
I don't use VS, so I won't comment on the error messages specifically (at least now). However one thing jumps out at me immediately when looking at your code.

In invItem.h, I suspect that description, cost and units (lines 5,6,7) are intended to be the private member data of an object of class invItem. In their current location, they are outside of the class definition which begins at line 8. They should be inside the class definition, below the current line 10 which marks the beginning of the private section.
You are right, In the book, they should be private. But that shouldn't make a difference as the source.cpp doesn't call any of that. I agree that's a bad practice though.

I'll try to put those inside Private and see what happen.

ThanksEDIT:
I put all those in Private. I updated post#67. You can take a look to verify. I copy into the new project, it works. but in the original project, the error window is exactly the same as in post #67.
 
Last edited:
Technology news on Phys.org
  • #72
Jarvis323 said:
I'm not sure where to start because there are some major fundamental problems with it. I think it might be time to go back to the books. Then maybe just delete this program entirely and start over following the book more closely.

But just to let you know, the errors are due to the global variables in the header file. The contents of the header file are inserted into the files that include it. In your case, you're inserting those global variables into multiple different cpp files, and that means you have multiple definitions of them.
I am working on that also. I am still checking my c-string stuffs, I have to go back to my notes, have not work on c-string for a while. Got into habit of using std::string whenever called for...Just when I feel comfortable!I want to emphasize, the name of the project that has problem is called 13.2. It has been giving me problem as of yesterday when I still using std::strings. I have worked on it, copy over to the temp project and another one. Those ALWAYS worked. project 13.2 consistently failed. I just did one more time putting those variables pointed out by jtbell, ran again in both 13.2 and temp, 13.2 failed and temp works just fine. This is really strange.

Thanks
 
Last edited:
  • #73
You are right, In the book, they should be private. But that shouldn't make a difference as the source.cpp doesn't call any of that. I agree that's a bad practice though.

It's more than that. It's completely outside the class. You can't have a variable like that in a header file as the compiler error explains. But even if you could, you should realize that every inventory item would be sharing the same description, cost and units variable. Each time you added a new inventory item, it would just overwrite the value of those variables.

Besides that, you're calling new, but not delete. So you also have a memory leak.

yungman said:
I am working on that also. I am still checking my c-string stuffs, I have to go back to my notes, have not work on c-string for a while. Got into habit of using std::string whenever called for...Just when I feel comfortable!

Thanks
I think for Inventory item, it might make sense to have a fixed size C-string so that you can use your binary IO in a straightforward way, and have guarantees on the storage requirements. I don't think performance or memory is a concern here. You can still use string while storing just a char array in InvItem if you want to. You could write something like this.

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{

private:

    static const int DESC_SIZE = 21;
    char m_description[ DESC_SIZE ]; // m_ prefix reminds you this is a member variable
    double m_cost;
    int m_units;

public:

    invItem()
    {
        m_description[ 0 ] = '\0';
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        std::snprintf(
            m_description,
            DESC_SIZE,
            "%s",
            d.c_str() );
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    std::string getDesc() const { return std::string( m_description ); }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif

C:
#include "invItem.h"

#include <iostream>
#include <iomanip>

int main()
{
    invItem item1( "Hammer", 6.95, 12 );

    cout << left << setw(30) << " Item description: " << item1.getDesc() << "\n";
    cout << left << setw(30) << " Cost: " << "$" << item1.getCost() << "\n";
    cout << left << setw(30) << " Units on hand: " << item1.getUnits() << "\n\n";

    return 0;
}

Or if you just want to use a string and try to still save memory.

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{

private:

    string m_description;
    double m_cost;
    int m_units;

public:

    invItem()
    {
        m_description.reserve( 20 );
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        m_description = d;
        m_description.shrink_to_fit();
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    const std::string & getDesc() const {  m_description; }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif

Or if you want dynamic C-strings, something like this

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{
private:

    char * m_description;
    double m_cost;
    int m_units;

public:

    // make sure memory allocated for m_description is freed when the object is destroyed
    ~invItem()
    {
        delete m_description;
    }

    invItem()
    {
        m_description = nullptr;
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        m_description = nullptr;
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        if( m_description != nullptr )
        {
            delete m_description;
        }

        const size_t NEW_SIZE = d.length() + 1;
        m_description = new char[ NEW_SIZE ];

        std::snprintf(
            m_description,
            NEW_SIZE,
            "%s",
            d.c_str() );
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    char * getDesc() const { return m_description; }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif
 
Last edited:
  • Like
Likes yungman
  • #74
Jarvis323 said:
It's more than that. It's completely outside the class. You can't have a variable like that in a header file as the compiler error explains. But even if you could, you should realize that every inventory item would be sharing the same description, cost and units variable. Each time you added a new inventory item, it would just overwrite the value of those variables.

Besides that, you're calling new, but not delete. So you also have a memory leak.

......
Hi Jarvis

Thanks for helping. I only reply on the first section. I have to copy your codes to look at it in VS on the second part.

I follow the book, I am still learning about Constructor.

This is copy of the book on the same problem, I just put in the first part on InventoryItem.h( I am lazy, I called invItem.h), same as I use L instead of the long DEFAULT_SIZE:
Book invItem.h.jpg
This is the source.cpp in the book:
Book source.cpp.jpg


Notice the line I drew red line. It doesn't work. I have to use char cAr[]="Hammer". The book is not very good in this chapter.

This is the pdf of the book. This is from p755 to p757 in case.
https://cplusplushelp.weebly.com/uploads/2/5/6/5/25655197/0136022537.pdf

I'll look at the second part of your code before I reply.

Thanks
 
Last edited:
  • #75
If I were the one writing this program, I would use std::string throughout, including the 'description' data member. Nevertheless, I think yungman should write it both ways as an educational exercise: one version using C-strings, and a second version using std::string.
 
  • Like
Likes yungman
  • #76
yungman said:
Hi Jarvis

Thanks for helping. I only reply on the first section. I have to copy your codes to look at it in VS on the second part.

I follow the book, I am still learning about Constructor.

This is copy of the book on the same problem, I just put in the first part on InventoryItem.h( I am lazy, I called invItem.h), same as I use L instead of the long DEFAULT_SIZE:
View attachment 270998This is the source.cpp in the book:
View attachment 270999

Notice the line I drew red line. It doesn't work. I have to use char cAr[]="Hammer". The book is not very good in this chapter.

This is the pdf of the book. This is from p755 to p757 in case.
https://cplusplushelp.weebly.com/uploads/2/5/6/5/25655197/0136022537.pdf

I'll look at the second part of your code before I reply.

Thanks
C++ allows a const to be in a header file without causing duplicate symbols but not a variable. Also, every InvItem can share the same DEFAULT_SIZE but not the same description. It's still not great to put the const outside the class in this case though because DEFAULT_SIZE isn't needed outside of the class.
https://stackoverflow.com/questions/12042549/define-constant-variables-in-c-header

I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription. Nothing in the part you posted has any errors that I can see.
 
  • Like
Likes Vanadium 50
  • #77
Jarvis323 said:
I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription.

Here's what yungman didn't tell us (from the book):

We have also added mutator functions that set values for description, cost, and units.
Program 13-12 demonstrates the class. (This file is also stored in the Student Source Code
Folder Chapter 13\InventoryItem Version 2
.)

(emphasis mine)

So of course this doesn't work. The book is using a subset of the code to illustrate something else: in this case constructors, not strings.
 
  • Like
Likes Jarvis323
  • #78
jtbell said:
If I were the one writing this program, I would use std::string throughout, including the 'description' data member. Nevertheless, I think yungman should write it both ways as an educational exercise: one version using C-strings, and a second version using std::string.
Yes, I am not in position to say which way is better. But, it's time for me to sweat it out a little. Believe me, I am sweating it out right now because the pointer for c-string and std::string is very different as the name of c-string is actually the starting address, and passing c-string in parameter is the address already. Also strlen() and all are different. Particular strncpy_s()....

Also, I am not as familiar with calling function to have {return ptr}, I always use void function and use pass by reference in the (). It's time for me to practice return. I don't like function return type, I use passing reference parameter from day one. This is giving me problem right now. These two are making my head spin right now!:nb)?:)

Thanks
 
  • #79
Vanadium 50 said:
Here's what yungman didn't tell us (from the book):
(emphasis mine)

So of course this doesn't work. The book is using a subset of the code to illustrate something else: in this case constructors, not strings.
Did you read my question? Why the same code won't work in one project consistently, but the EXACT code COPIED over to a new temp project AND another existing project compile and ran? Exact same two files copied into 3 projects, two works, one doesn't.

This is NOT just about my code having problem.
 
Last edited:
  • #80
yungman said:
Did you read my question?

I was answering jarvis.

As far as not having the CD, maybe you should get it.
 
  • #81
Jarvis323 said:
C++ allows a const to be in a header file without causing duplicate symbols but not a variable. Also, every InvItem can share the same DEFAULT_SIZE but not the same description. It's still not great to put the const outside the class in this case though because DEFAULT_SIZE isn't needed outside of the class.
https://stackoverflow.com/questions/12042549/define-constant-variables-in-c-header

I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription. Nothing in the part you posted has any errors that I can see.
This is the code I got from the CD with the book and I want to show what doesn't work. It's in the source.cpp file

This is the source.cpp. I have to make correction to line 13, 21 and 26 to make it work using char cAr1,cAr2 and cAr3.
C++:
// This program demonstrates a class with overloaded constructors.
#include <iostream>
#include <iomanip>
#include "InventoryItem.h"
using namespace std;

int main()
{
   // Create an InventoryItem object and call
   // the default constructor.
   InventoryItem item1;
   char cAr1[] = "Hammer";//New line to fix problem
  // item1.getDescription("Hammer");// Set the description
   item1.setDescription(cAr1); //This line works
   item1.setCost(6.95);            // Set the cost
   item1.setUnits(12);             // Set the units

   // Create an InventoryItem object and call
   // constructor #2.
   char cAr2[] = "Pliers";//added
   //InventoryItem item2("Pliers");
   InventoryItem item2(cAr2); //This line works
   // Create an InventoryItem object and call
   // constructor #3.
   char cAr3[] = "Wrench";
   //InventoryItem item3("Wrench", 8.75, 20);
   InventoryItem item3(cAr3, 8.75, 20);
   cout << "The following items are in inventory:\n";
   cout << setprecision(2) << fixed << showpoint;
  
   // Display the data for item 1.
   cout << "Description: " << item1.getDescription() << endl;
   cout << "Cost: $" << item1.getCost() << endl;
   cout << "Units on Hand: " << item1.getUnits() << endl << endl;

   // Display the data for item 2.
   cout << "Description: " << item2.getDescription() << endl;
   cout << "Cost: $" << item2.getCost() << endl;
   cout << "Units on Hand: " << item2.getUnits() << endl << endl;

   // Display the data for item 3.
   cout << "Description: " << item3.getDescription() << endl;
   cout << "Cost: $" << item3.getCost() << endl;
   cout << "Units on Hand: " << item3.getUnits() << endl;
   return 0;
}

Also, I have to change all the strcpy() to strncpy_s() in InventoryItem.h as VS won't compile.
C++:
// This class has overloaded constructors.
#ifndef INVENTORYITEM_H
#define INVENTORYITEM_H
#include <cstring>   // Needed for strlen and strcpy

// Constant for the description's default size
const int DEFAULT_SIZE = 51;

class InventoryItem
{
private:
   char *description;  // The item description
   double cost;        // The item cost
   int units;          // Number of units on hand
public:
   // Constructor #1
   InventoryItem()
      { // Allocate the default amount of memory for description.
        description = new char [DEFAULT_SIZE];
       
        // Store a null terminator in the first character.
        *description = '\0';
       
        // Initialize cost and units.
        cost = 0.0;
        units = 0; }

   // Constructor #2
   InventoryItem(char *desc)
      { // Allocate just enough memory for the description.
        description = new char [strlen(desc) + 1];
       
        // Copy the description to the allocated memory.
        strncpy_s(description, strlen(desc) + 1,desc, strlen(desc) + 1);
       
        // Initialize cost and units.
        cost = 0.0;
        units = 0; }
       
   // Constructor #3
   InventoryItem(char *desc, double c, int u)
      { // Allocate just enough memory for the description.
        description = new char [strlen(desc) + 1];
       
        // Copy the description to the allocated memory.
        strncpy_s(description, strlen(desc) + 1, desc, strlen(desc) + 1);
       
        // Assign values to cost and units.
        cost = c;
        units = u; }
       
   // Destructor
   ~InventoryItem()
      { delete [] description; }

   // Mutator functions
   void setDescription(char *d)
      { strncpy_s(description, 10, d, 10);}
   void setCost(double c)
      { cost = c; }
     
   void setUnits(int u)
      { units = u; }

   // Accessor functions
   const char *getDescription() const
      { return description; }
        
   double getCost() const
      { return cost; }

   int getUnits() const
      { return units; }
};
#endif

EDIT:
I put these two files in the problem project, to my surprise, it works.


Thanks for your time to help me.

Alan
 
Last edited:
  • #82
Vanadium 50 said:
I was answering jarvis.

As far as not having the CD, maybe you should get it.
But you were calling me out in a sarcastic way. I use the CD from the complete edition of the same book and it has the codes like I just posted to Jarvis. I did have to fix the code to make it work. Now I am going to copy this code into the problem project to see.
 
  • #83
yungman said:
But you were calling me out in a sarcastic way. I use the CD from the complete edition of the same book and it has the codes like I just posted to Jarvis. I did have to fix the code to make it work. Now I am going to copy this code into the problem project to see.
You made one mistakes copying the code from the book. On line 13, item1.getDescription("Hammer"); should be item1.setDescription("Hammer");

The book is probably a little outdated, because passing a string literal as a char * is now depreciated (it was legal, but now it's not). You have to use const char *, as the parameter type now for it to work.
 
  • Like
Likes yungman
  • #84
Jarvis323 said:
You made one mistakes copying the code from the book. On line 13, item1.getDescription("Hammer"); should be item1.setDescription("Hammer");

The book is probably a little outdated, because passing a string literal as a char * is now depreciated (it was legal, but now it's not). You have to use const char *, as the parameter type now for it to work.
Ha! The book is wrong, I did not type this from reading the book, I actually copied the code from the CD and ran. I did not even see they were get instead of set!

But still in line21 and line 26 is the same way. You cannot using set("Hammer"...), it has to be from a c-string.

That's something, the code from CD is wrong.

You have SHARP eyes!

Thanks
 
  • #85
yungman said:
Ha! The book is wrong, I did not type this from reading the book, I actually copied the code from the CD and ran. I did not even see they were get instead of set!

But still in line21 and line 26 is the same way. You cannot using set("Hammer"...), it has to be from a c-string.

That's something, the code from CD is wrong.

You have SHARP eyes!

Thanks
It probably wasn't wrong when it was made. It's outdated.
 
  • Like
Likes yungman
  • #86
Anyway, for whatever reason, The problem project now doesn't fail anymore. I even went back to post 67 and copy the two files and put them into the problem project, it works now.

I guess this just chuck it into the X-File. I definitely did NOT change any setting. At this point, I know better after working a few days on VS. It was failing for over a day until I copied the original two files from the book's CD in. Somehow it's not failing anymore.

I am sure there are a lot of thing you can criticize in my codes, but that's really not the point. Something did happen.

Thanks for all your time.
 
  • #87
I just step through the program in post #81 one step at a time. I put breakpoint on each and every single line of code. I use F5 to step through one line at a time and LABEL what steps of the line from 0 to 44.

I want to see how the overload Constructor works. How does the main() step through the functions in the Class .h file. It really gives me an insight to how the whole program works. It is a lot clearer how the Constructors work particularly with over load.

I did not know that even though the pointer description is the same name for all 3 Constructors to allocate dynamic memory, EACH has it's separate address so I actually have 3 segments of memory each for one Constructor! This really answer a lot of my questions.

Just want to thank you guys for all the help. I really feel I am learning.

Alan
 
  • #88
yungman said:
I just step through the program in post #81 one step at a time. I put breakpoint on each and every single line of code. I use F5 to step through one line at a time and LABEL what steps of the line from 0 to 44.
F5 is used to Continue executing the program. If you didn't have breakpoints, pressing F5 would cause all program lines to execute, either to the end or to some line asking for input.
What I do is to put one breakpoint somewhere near the beginning of the code in main(), hit F5, and then use F10 to single step a line of code at a time.
I use F10 (Step Over) and F11 (Step Into) a lot.
Step Into (F11) takes you into the body of a function so you can see exactly what constructors and other functions are doing.
Step Over (F10) just executes that line of code without taking you into the function body.
yungman said:
I want to see how the overload Constructor works. How does the main() step through the functions in the Class .h file. It really gives me an insight to how the whole program works. It is a lot clearer how the Constructors work particularly with over load.
Here's a better way to use VS.
Put a breakpoint in main() at this line:
InventoryItem item1;
Press F5 - the line above will be ready to execute.
Press F11 to take you into the body of your default constructor.
Press F10 to skip over the function call, and take you to the next line in main().

yungman said:
I did not know that even though the pointer description is the same name for all 3 Constructors to allocate dynamic memory, EACH has it's separate address so I actually have 3 segments of memory each for one Constructor!
It's not clear what you're saying here about three segments of memory. Memory segments are usually divided into stack, heap, and static memory. Each InventoryItem object that you create has its own chunk of memory on the heap, that will contain the item description. You have three overloaded constructors: a default constructor with no parameters, a constructor with just a description parameter, and a constructor with all three parameters.

Every InventoryItem object that you create will have three data members -- description, cost, and units. The difference is which constructor you use and whether the data members are filled in by a constructor or not.
 
  • Like
Likes yungman
  • #89
Hi Mark

Really miss you yesterday on the strange thing with VS I encounted, it's too late now, I cannot make it fail anymore. I really looked into it, looking at Solution Explorer, Project Properties, all the options. Using all the knowledge I learned in the pass few days from you and others to look and still cannot find what was the difference in the setting.

Thanks for the suggestion on F11, I have to copy your response and print it out to read it slowly. I read F11, it said "step into" and show the dot. To me it's like step to the next break point. I did NOT know F11 is stepping one line at a time. So I did it the dumb way...dotted every single line! So I hit F5, I step through every line.

I am really having a ball with the debugger. Yes, 3 constructor creating 3 separate chunk of memories using the same overload pointer description.I want to ask you and the other experts. Do people use overload Constructors like in my example from the book in real world? It is interesting to learn...BUT in real life where programs are a lot bigger and much more complicate. Is it even a good practice to use overload Constructors where you pretty much have to be forced to use overload variables like description, units, cost in the program in post #67? That all have the same name and you have to keep tract of them at all times.

I know you have no choice in using overload Constructors in some cases, BUT I know you can use Overload inside the program also. Do you really want to do that in the program? Seems like it's easier to just use different names. Like if I can help it, I would use description1, description2, description3, cost1, cost2, cost3 etc. As much as possible instead going into overload just because I can do it. One thing I learn from experience, it's nice to have clever circuit/code, more elegant and fancier. But in real life working environment, just make it simple, straight forward whenever possible. It doesn't pay to be fancy. People don't care how you do it, they just care you get the job done consistently and reliably. the fancier it is, the more likely to make mistake. To me, that's the golden rule.

Thanks
 
Last edited:
  • #90
yungman said:
I did NOT know F11 is stepping one line at a time. So I did it the dumb way...dotted every single line! So I hit F5, I step through every line.
F11 will step into the function one step. F10 will step over the function call and go to the line right after the call to the function. If you know that a function is working correctly it makes more sense to step over (F10) the function call, but if you're debugging the function you want to step into it (F11).
yungman said:
BUT in real life where programs are a lot bigger and much more complicate. Is it even a good practice to use overload Constructors where you pretty much have to be forced to use overload variables like description, units, cost in the program in post #67? That all have the same name and you have to keep tract of them at all times.
Yes, it's good practice to have multiple constructors, and you haven't even come to a couple more -- copy constructor and move constructor.
Regarding overload variables, there's no such thing. One thing that would help you with your question is to use a certain style for the class members, and a different style for the constructor parameters. A common style for class member names is m_name. The 'm' at the beginning is a clue that this is a class member name.
Here are your revised class definition and two of your constructors, modified to use this style.
C++:
class InventoryItem
{
private:
    char *m_description;  // The item description
    double m_cost;        // The item cost
    int m_units;          // Number of units on hand
public:
.
.
.
C++:
// Constructor #2
    InventoryItem(char *description)
    { // Allocate just enough memory for the description.
        m_description = new char[strlen(description) + 1];

        // Copy the description to the allocated memory.
        strncpy_s(m_description, strlen(description) + 1, description, strlen(description) + 1);

        // Initialize cost and units.
        m_cost = 0.0;
        m_units = 0;
    }
C++:
// Constructor #3
    InventoryItem(char *description, double cost, int units)
    { // Allocate just enough memory for the description.
        m_description = new char[strlen(description) + 1];

        // Copy the description to the allocated memory.
        strncpy_s(m_description, strlen(description) + 1, description, strlen(description) + 1);

        // Assign values to cost and units.
        m_cost = cost;
        m_units = units;
    }
Now the parameters to these two constructors have the same names, so you don't have to come up with a bunch of different parameter names for each constructor, and the class data member names are distinct from the constructor parameter names.
yungman said:
I know you have no choice in using overload Constructors in some cases, BUT I know you can use Overload inside the program also. Do you really want to do that in the program? Seems like it's easier to just use different names. Like if I can help it, I would use description1, description2, description3, cost1, cost2, cost3 etc. As much as possible instead going into overload just because I can do it. One thing I learn from experience, it's nice to have clever circuit/code, more elegant and fancier. But in real life working environment, just make it simple, straight forward whenever possible.
This is a bad idea to use all those variants with numbers at the end. In the examples I show above, if two constructors do something with the same class data member, the parameter names can be, and should be, the same.

One thing that you should realize is that there is a hierarchy of programmers, especially in large programs, in which a team of programmers is involved. One level of programmer in the hierarchy designs and implements classes, and another level writes applications that use those classes. A class designer creates overloaded constructors and member functions as a convenience to application programmers. That way, an application programmer can create a class instance, initializing it with zero, one, or more parameters, depending on what his or her needs. In what you're doing, you're implementing the class, and writing code that uses the class, which is not at all the way things work in the software industry.
 
  • Like
Likes yungman
  • #91
I just finish my notes on stepping through the program and to show description, cost and units have different addresses for the 3 overload constructors. I attached the page of my notes. This is getting more complicated, I really have to stop, going through it to see how constructors are in action.

Seems like Constructor is NOT being run right at the beginning of the program like Distructor that run right before the end of the program whether it's called in main() or not. Constructor has to be called in the main() before it's executed. Like in the program that doesn't go to the first Constructor#1 until the line invItem item1, invItem item2 for Constructor#2 and invItem item3 for Constructor#3.
 

Attachments

  • Example of Overload Constructor.docx
    330.2 KB · Views: 143
  • #92
Mark44 said:
A common style for class member names is m_name

Going further, it is good to do this to separate members from methods. So you might have member m_radius in your class Circle, but also methods Radius, Diameter and Area. Or possibly getRadius, getDiameter and getArea. Whet you don't want is Diameter, getArea, get_the_circumference and if you want the radius, you need to know to access the member directly.

That makes the programmer's life easier. And the programmer might be Future You.

It's also a good idea to make m_radius private. That way that when you decide that m_diameter would be a better idea, you only need to make that change within the class. Code that merely uses that class remains unchanged.
 
  • Like
Likes sysprog
  • #93
Thanks Mark for the reply.

I have a question. From looking at breakpoints through the program, I notice the values of description, &cost and &units disappear RIGHT AFTER stepping beyond the Constructor#1 as shown. I open the Immediate Window and print them out right after the first breakpoint to line 10 in invItem.h file. I show I have the addresses of all 3 in the first picture.
Step through constructor.jpg

But I step to the second break point, all the addresses are gone:
Step after constructor.jpg


The program is not done with Constructor#1 yet, why all the 3 are "undefined" already?

The reason I want to look at is all 3 were initialized to " ", 0.00 and 0 when initialized. Then the program should overwrite to "Hammer", 6.95 and 12. I never get to verify that.

Thanks Mark.
 
  • #94
yungman said:
I notice the values of description, &cost and &units disappear RIGHT AFTER stepping beyond the Constructor#1 as shown. I open the Immediate Window and print them out right after the first breakpoint to line 10 in invItem.h file. I show I have the addresses of all 3 in the first picture.
yungman said:
But I step to the second break point, all the addresses are gone:
The program is not done with Constructor#1 yet, why all the 3 are "undefined" already?
No, the program is done with Constructor #1. That's what happened in the line
InvItem item1;
In the first screen shot, the code is executing within the default (i.e., no parameter) constructor InvItem(), so the names description, cost, and units are within scope.
In the second screen shot, the code is executing in main(), and the default InvItem() constructor has already created an object, the one named item1. The class members description, cost, and units are private, so aren't accessible outside the class (that is, outside the class member functions). That's why these identifiers don't show up any more.
 
Last edited:
  • Like
Likes yungman
  • #95
Mark44 said:
No, the program is done with Constructor #1. That's what happened in the line
InvItem item1;
In the first screen shot, the code is executing within the default (i.e., no parameter) constructor InvItem(), so the names description, cost, and units are within scope.
In the second screen shot, the code is executing in main(), and the default InvItem() constructor has already created an object, the one named item1. The class members description, cost, and units are private, so aren't accessible outside the class (that is, outside the class member functions). That's why these identifiers don't show up any more.
I see, it's private, so the moment it leaves Constructor#1, I cannot see it anymore.

But even when I was in the constructor, I still cannot see the new values, maybe I have been trapping them in the wrong place. But at least I proved the address already to show I have 3 sets of overload variables.

Thanks for you reply,

Ha ha, do you know of anyway to step BACKWARD in debugger?! You ever encounter you do F11 and you say "ooops", you regret having that itchy finger and you wish you can just go back one step? I have to hit shift-F5 and start all over again so many times!

I know you can take the program back by hovering the mouse on the line and you'll see a little arrow and you click, you force the program to go back. BUT the damage is done, values are changed. I am talking about reversing the direction and restore the execution as if it never execute...Am I pushing my luck?

Thanks
 
Last edited:
  • #96
I think maybe you are confused about what the class is. You can think of it like a blueprint or schematic.

It's only when you create an object/instance of them (construct) that an object/instance of the class exists with the variables in memory. A constructor is the first function that is called when you make one. And each one you make is a different one with different memory.

So it's not because you use a different constructor that description is different, it's because you made a new and different InvItem. If you made 3 different instances using the same constructor, they would of course still have different memory/variable instances. Just like 3 different houses use different wooden beams, even though the blueprint just shows one.
 
  • Like
Likes yungman
  • #97
Jarvis323 said:
I think maybe you are confused about what the class is. You can think of it like a blueprint or schematic.

It's only when you create an object/instance of them (construct) that an object/instance of the class exists with the variables in memory. A constructor is the first function that is called when you make one. And each one you make is a different one with different memory.

So it's not because you use a different constructor that description is different, it's because you made a new and different InvItem. If you made 3 different instances using the same constructor, they would of course still have different memory/variable instances. Just like 3 different houses use different wooden beams, even though the blueprint just shows one.
Thanks for reminding me. I read and even put in my notes Class is the blueprint only. But when dealing with codes, it quickly becomes just an external function...like a function call to a function outside of the project.

Like I traced the whole project step by step, it actually go from main() to invItem.h, follow the code, execute and return back to main(), then call the second and third Constructors, then call member function() to output the values to the CRT. It's just like an external function.

I honestly don't see the Class object is the blueprint. How is the invItem.h header file the blueprint of the whole program? Can you explain what in the invItem.h the blueprint of the project?

I know you are right, I just can't see it.

Thanks
 
Last edited:
  • #98
The class, class InvItem { ... }; is like a blueprint for an InvItem. It is not until one of those is constructed that an object exists. The analogy was meant to help you understand the difference between an object and a class.
 
Last edited:
  • #99
Jarvis323 said:
The class, class InvItem { ... }; is like a blueprint for an InvItem. It is not until one of those is constructed that an object exists. The analogy was meant to help you understand the difference between an object and a class.
So invItem is a Class, the blue print of allocating memory using description and two variables cost and units. It is a blue print until the program say invItem item1 than item1 is the object being created. I see now invItem Class is NOT the blueprint of the program, just one of the structure like item1, 2 or 3.

How is this different from say an external function having a structure
C++:
struct invItem
{
char* desc = new char[L];
double cost;
int unit;
}

I know there are lot more detail, I am not saying they are the same. But you get my point that the external structure is not a blue print, but you can make it work the same way.

Only difference is in Class, you can create object over and over, where in structure, you have to create the second and third structure for 3 of them. Is that what you call the blueprint to create object?

If so, then I am starting to get it.

Thanks
 
  • #100
yungman said:
Ha ha, do you know of anyway to step BACKWARD in debugger?! You ever encounter you do F11 and you say "ooops", you regret having that itchy finger and you wish you can just go back one step?
In the Debug menu, there is Step Backward, or Alt [.
yungman said:
I read and even put in my notes Class is the blueprint only.
It's the same idea for a struct. The struct definition is the template for how a struct instance is laid out in memory.
yungman said:
Like I traced the whole project step by step, it actually go from main() to invItem.h, follow the code, execute and return back to main(), then call the second and third Constructors, then call member function() to output the values to the CRT. It's just like an external function.
That's the wrong way to think about things. Instead of thinking about the files where the functions are defined, the member functions of a struct are internal to the class. Whether the function definitions appear in the header file or in another .cpp file is really irrelevant.
yungman said:
I honestly don't see the Class object is the blueprint. How is the invItem.h header file the blueprint of the whole program? Can you explain what in the invItem.h the blueprint of the project?
The header file isn't the class blueprint -- the class definition, class InvItem, in this case -- is the blueprint, or template.
yungman said:
How is this different from say an external function having a structure
C++:
struct invItem
{
   char* desc = new char[L];
   double cost;
   int unit;
}
It's different because this struct doesn't have any member functions. It's also different in that the three data members are public.
yungman said:
Only difference is in Class, you can create object over and over, where in structure, you have to create the second and third structure for 3 of them. Is that what you call the blueprint to create object?
In C++, the only difference between a struct and a class is that members of a struct are public, by default. That's the only difference. A struct can have member functions, just like a class.
 
Last edited:
  • Like
Likes yungman
  • #101
Mark44 said:
In the Debug menu, there is Step Backward, or Alt [.
It's the same idea for a struct. The struct definition is the template for how a struct instance is laid out in memory.
That's the wrong way to think about things. Instead of thinking about the files where the functions are defined, the member functions of a struct are internal to the class. Whether the function definitions appear in the header file or in another .cpp file is really irrelevant.
The header file isn't the class blueprint -- the class definition, class InvItem, in this case -- is the blueprint, or template.
It's different because this struct doesn't have any member functions. It's also different in that the three data members are public.
In C++, the only difference between a struct and a class is that members of a struct are public, by default. That's the only difference. A struct can have member functions, just like a class.
Thanks for the reply.

I don't see Alt[ in debug menu. I see F11 step in, F10 step over and shift-F11 step out.

Yes, I think toward the last part, I realize the .h file is not the blue print, only the invItem is the Class, that is the blue print to create item1, item2 and item3.

I did not realize struct is a blueprint also. So the difference is struct are all PUBLIC . Class is more complicate with private and public. I have not learn struct can have member function yet.

In struct st, you access the member by st.cost, I have not seen in the invItem item1 that I can access item1.cost like in struct. Is this because double cost is PRIVATE. that if I declare double cost in PUBLIC, I can access from program using item1.cost = 6.95? If that is true, this clears up more question for me.

Thanks for explaining this.
 
  • #102
yungman said:
the external structure is not a blue print,
No, it is a blueprint just like a class is. See page 592 of your book, where Gaddis introduces structures by defining a struct data type named PayRoll.
C++:
struct PayRoll
{
    int empNumber; // Employee number
    char name[SIZE]; // Employee's name
    double hours; // Hours worked
    double payRate; // Hourly pay rate
    double grossPay; // Gross pay
};
He then writes:

Gaddis said:
It’s important to note that the structure declaration in our example does not define a variable. It simply tells the compiler what a PayRoll structure is made of. In essence, it creates a new data type named PayRoll. You can define variables of this type with simple definition statements, just as you would with any other data type. For example, the following statement defines a variable named deptHead:

PayRoll deptHead;
After that that statement, there now exist "sub-variables" named deptHead.empNumber, deptHead.name, etc.

If you then have the following statement:

PayRoll teamLead;

you now also have "sub-variables" names teamLead.empNumber, teamLead.name, etc.

If PayRoll were a class instead of a struct, you could do the same two statements, and you would have the same "sub-variables". The only difference here is that you cannot access the "sub-variables" (member data) directly from your program. In a class object, only the member functions can access private member data directly.
 
  • Like
Likes yungman
  • #103
yungman said:
I don't see Alt[ in debug menu.
The debugger has to be running for this option to appear.
yungman said:
In struct st, you access the member by st.cost, I have not seen in the invItem item1 that I can access item1.cost like in struct. Is this because double cost is PRIVATE. that if I declare double cost in PUBLIC, I can access from program using item1.cost = 6.95? If that is true, this clears up more question for me.
Yes, if cost were listed among the public members of the class, you could access it directly from an object using the dot operator. This is not a good idea, as it defeats one of the major attributes of OO design, encapsulation -- a class should provide a set of accessors and mutators to limit access to the data members of a class.
 
  • #104
Mark44 said:
The debugger has to be running for this option to appear.
Yes, if cost were listed among the public members of the class, you could access it directly from an object using the dot operator. This is not a good idea, as it defeats one of the major attributes of OO design, encapsulation -- a class should provide a set of accessors and mutators to limit access to the data members of a class.
Yes, I was running debug by hitting F5 first and stop at the break point before I check. This is the picture. I don't see it.
Step back.jpg


Thanks for clearing the private public variable up. I understand not to put that in public, just want to confirm I can do that if I put it in public and can use dot to access it.

Seems like after the first semester C++, things are getting much more complicate, it really takes time to really understand it. It's not like I can fly over the chapters.

Thanks for your time.
 
  • #105
jtbell said:
No, it is a blueprint just like a class is. See page 592 of your book, where Gaddis introduces structures by defining a struct data type named PayRoll.
C++:
struct PayRoll
{
    int empNumber; // Employee number
    char name[SIZE]; // Employee's name
    double hours; // Hours worked
    double payRate; // Hourly pay rate
    double grossPay; // Gross pay
};
He then writes:After that that statement, there now exist "sub-variables" named deptHead.empNumber, deptHead.name, etc.

If you then have the following statement:

PayRoll teamLead;

you now also have "sub-variables" names teamLead.empNumber, teamLead.name, etc.

If PayRoll were a class instead of a struct, you could do the same two statements, and you would have the same "sub-variables". The only difference here is that you cannot access the "sub-variables" (member data) directly from your program. In a class object, only the member functions can access private member data directly.
Thank you for the explanation. I am getting this.

Thanks
 

Similar threads

Replies
22
Views
3K
Replies
13
Views
2K
Replies
8
Views
2K
Replies
8
Views
2K
Replies
89
Views
5K
Replies
1
Views
1K
Back
Top