Nested class test with string and const char* types

I am working on an API which uses nested classes and const char* members. I came across this issue when trying to understand about nested classes with a sample class. The idea is every person with a name has a home address by default which is set by the constructor when invoked. Later through main function we can create different addresses like office, college, etc.

The problem is string types and int types set inside the constructor remain set. While the const char* types are momentarily set and then they turn \0 at some address after exiting. And when I try to print it shows garbage for const char* type members "State" and "City". But the string types teststr and int type H.no work as expected.

Kindly let me know what is going on. How to resolve the const char* pointing to null on exit?
Thanks in advance.

1
2
3
4
5
6
7
8
9
10
/* main.cpp */
#include "Person.h"
int main()
{
	Person john("John"); // makes a default home address.
	john.printAddress(&john.home); // print the home address set by constructor.
	cout << john.name << endl; // Prints name as expected. 
	system("pause");
	return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*  Person.h  */
#include <string>
#include <iostream>
using namespace std;

class Person
{
public:
	Person(const char*);
	const char* name;
	class Address
	{
	public:
		const char* City;
		const char* Street;
		std::string teststr;
		int H_No;
	}home;
	void printAddress(Address*);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Person.cpp */
#include "Person.h"

Person::Person(const char* _name)
{
	name = _name; // assigned to public member "name" of the Person class.
	cout << "I am " << name << " in your database. Give me my.." << endl;
	cout << "homeCity " << "homeStreet " << "homeNo" << endl;
	string cty, strt; int no;
	cin >> cty >> strt >> no; //Get the values..
	home.City = cty.c_str(); // convert string to const char *
	home.Street = strt.c_str(); // convert string to const char *
	home.H_No = no; // integer ..
	home.teststr = "all ok"; //dummy test msg of string type..
}

void Person::printAddress(Address *type)
{
	cout << "City" << type->City << endl; //Doesnt work as expected
	cout << "Street" << type->Street << endl;//Does nt work as expected.
	cout << "teststr " << type->teststr << endl; //works fine
	cout << "H.no " << type->H_No << endl;// works fine
}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Person::Person(const char* _name)
{
    name = _name;
    cout << "I am " << name << " in your database. Give me my.." << endl;
    cout << "homeCity " << "homeStreet " << "homeNo" << endl;
    string cty, strt; int no;
    cin >> cty >> strt >> no;
    //pointer returned by c_str() is valid until calling any non-const member on corresponding string.
    home.City = cty.c_str(); //Set home.City to point to some internal buffer of cty
    //Now City poionts to some buffer. Any changes to it will be reflected on it.
    home.Street = strt.c_str(); //Ditto
    home.H_No = no; 
    home.teststr = "all ok"; //assign const char* string literal to string teststr.
    //As string copies data in itself and handles own storage, nothing aside from direct operation on it can change it
} //cty and strt are destroyed here. Pointers to their buffer provided by c_str() are now invalid 
You're not copying your strings properly. Person::City and Person::Street are pointers. In your constructor, you're setting them to point to memory that is managed by the std::string objects cty and strt. However, at the end of the constructor, those string objects fall out of scope and are destroyed. This means that the memory that home.City and home.Street are pointing to is no longer reserved, and you can't rely on that memory to contain the data you're expecting.

I have to wonder why you're using char* for strings in your class. Why not simply make them std::string? After all, you're already using std::string for the local variables in the constructor.



Last edited on
Thank you very much for your response MikeyBoy and MiiNiPaa now it makes sense to me.

@MikeyBoy I am planning to wrap a C++ API to Python in the near future which extensively uses char* for strings. So I am trying to understand better with examples.
Topic archived. No new replies allowed.