this is what i have, and i have lots of mistakes in class to class...and friends functions
dont know why, need your help
CCar.h:

#ifndef _CCar_H							//מונע אפשרות להכללות כפולות של המודול
#define _CCar_H
#include "CWorker.h"
#define LEN_N_FIRMA 20
//class CWorker;
class CCar
{
	char m_firma[LEN_N_FIRMA];		// car firma
	int m_price;	  							   // car price
	friend CWorker::CWorker(const char*,const char *firma ,int price ,int numOfChildren);
public:
	CCar(const char *firma='\0',int price=0);	
};
#endif

CWorker.h:

#define LEN_N_W 20
#define LEN_C 10

class CWorker
{
	char m_name[LEN_N_W];			// worker's name
	CCar  *m_pCar;							// car
	//CChild m_cArr[LEN_C];				// array of children
	int m_numChildren;						// number of children to this worker
//	???  m_totalNumChildren;				// counter of all children of all workers
public:
	CWorker(const char*,const char *firma='\0' ,int price=0 ,int numOfChildren=0);
//	CWorker(const CWorker&);	
	~CWorker();	
	void showWorker()const;

};
#endif

CCarr.cpp

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <assert.h>
#include <string>
#include "CCar.h"

using namespace std;

CCar::CCar(const char *firma, int price):m_price(price)
{
	strcpy(m_firma,firma);
}

CWorker.cpp:

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <assert.h>
#include <string>
#include "CWorker.h"
#include "CCar.h"
#include "CChild.h"

using namespace std;

CWorker::CWorker(const char *name,const char *firma,int price,int numOfChildren):m_numChildren(numOfChildren)
{
	strcpy(m_pCar->m_firma,firma);
	m_pCar->m_price=price;
	strcpy(m_name,name);
	m_pCar= new CCar();
	assert(m_pCar);
}

/*CWorker::CWorker(const CWorker&worker)
{
	int i;
	for(i=0;i<worker.m_numChildren;i++);		
	m_pCar=new CCar[i+1];							
	assert(m_pCar);
	memcpy(m_pCar,worker.m_pCar,(i+1)*sizeof(CCar));				
	m_numChildren=worker.m_numChildren;
	strcpy(m_name,worker.m_name);	 
}*/
CWorker::~CWorker()
{
	delete [] m_pCar;							
}
void CWorker::showWorker() const
{
	cout<<m_name<<":";
	cout<<endl;
}

main.cpp:

#include <iostream>
#include <assert.h>
#include "CCar.h"
#include "CChild.h"
#include "CWorker.h"

using namespace std;

void main()
{
	
	CCar car("Mercedes" , 50000);
	CWorker *Sasson  = new CWorker("Sasson Sassoni");
	assert(Sasson);

	Sasson->showWorker();
/*	addChild(*Sasson, CChild("Sassoniile", 3));
	addChild(*Sasson, CChild("Sassonchick", 7));
	Sasson->setCar("Mercedes", 900000);
	Sasson->showWorker();
	cout<<"======================\n" << endl;
	// compare cars by names only
	cout<< "Checking cars = " << car.isSameCar(*Sasson)<<endl<<endl;
	cout<<"======================\n" << endl;
	CWorker Rambo = *Sasson;
	Rambo.setName("Rambo");
	addChild(Rambo , CChild("Rambole" , 5));
	Rambo.showWorker();
	cout<<"======================\n" << endl;
	// array of children
	CChild A[] = { CChild("Shilgi1" , 1) , CChild("Shilgi2" , 2) , CChild("Shilgi3" , 3) };
	CWorker Shilgiya("Shilgiya" , "Fiat" , 22000   , A   ,  3);
	Shilgiya.showWorker();
	// the total number of children belongs to all workers exists
	cout<<"totalNumChildren (of all worker till now) = " <<
CWorker::showTotalNumChildren()<<endl<<endl;
	delete Sasson;
	cout<<"totalNumChildren (of all worker till now) = " <<
CWorker::showTotalNumChildren()<<endl<<endl;*/
}

i am not allude to change anything in CCar class..
would be pleased for any help.

I'm somewhat confused about this design. Why make CWorker's constructor a friend of CCar when you can simply construct a new CCar?

#define LEN_N_W 20

class CWorker
{
    char m_name[LEN_N_W];
    CCar m_Car;
public:
    CWorker(const char *name, const char *firma = "",int price = 0);
    void showWorker(ostream& out)const;
};

CWorker::CWorker(const char *name, const char *firma, int price)
    : m_Car(firma, price) // Delegate the work to CCar
{
    strcpy(m_name, name);
}

void CWorker::showWorker(ostream& out) const
{
    out << m_name << ":";
}

Pointers for the sake of using pointers is silly, and your code strikes me as using them unnecessarily. But if you want to continue using a pointer for the member it changes little:

#define LEN_N_W 20

class CWorker
{
    char m_name[LEN_N_W];
    CCar *m_pCar;
public:
    CWorker(const char *name, const char *firma = "",int price = 0);
    ~CWorker();
    void showWorker(ostream& out)const;
};

CWorker::CWorker(const char *name, const char *firma, int price)
    : m_pCar(new CCar(firma, price)) // Delegate the work to CCar
{
    strcpy(m_name, name);
}

CWorker::~CWorker()
{
    delete[] m_pCar;
}

void CWorker::showWorker(ostream& out) const
{
    out << m_name << ":";
}

The real problem that I see is in CWorker::showWorker(). If your ultimate goal is to show the data from m_pCar but can't change CCar, you're kind of screwed because CCar presently only allows CWorker's constructor as a friend, not CWorker as a whole. To give access to m_pCar's members, you'd need to do something truly ugly. For example:

#include <assert.h>
#include <string.h>
#include <iostream>

using namespace std;

#define LEN_N_W 20

class CCar; // Forward reference CCar for the pointer member

class CWorker
{
    char m_name[LEN_N_W];
    CCar *m_pCar;
    
    // Hack to access m_pCar's privates outside of the constructor
    const char* m_pCar_firma;
    const int& m_pCar_price;
public:
    CWorker(const char *name, const char *firma = "",int price = 0);
    ~CWorker();
    void showWorker(ostream& out)const;
};

// Be sure to define CCar *after* CWorker because the 
// friend declaration depends on CWorker being defined
#define LEN_N_FIRMA 20

class CCar
{
    char m_firma[LEN_N_FIRMA];
    int m_price;
public:
    CCar(const char *firma = "", int price = 0);
    friend CWorker::CWorker(const char *name, const char *firma, int price);
};

// Define the two class' members at your leisure
CWorker::CWorker(const char *name, const char *firma, int price)
    : m_pCar(new CCar(firma, price)), // Delegate the work to CCar
      m_pCar_firma(m_pCar->m_firma),  // Hack: make an alias into m_pCar
      m_pCar_price(m_pCar->m_price)   // Hack: make an alias into m_pCar
{
    strcpy(m_name, name);
}

CWorker::~CWorker()
{
    delete[] m_pCar;
}

void CWorker::showWorker(ostream& out) const
{
    // Use the aliases defined in the constructor to 
    // access m_pCar from a non-friend member function
    out << m_name << ": '" << m_pCar_firma << "' -- " << m_pCar_price;
}

CCar::CCar(const char *firma, int price)
    : m_price(price)
{
    strcpy(m_firma, firma);
}

// Test driver
//
int main()
{
    CWorker Sasson("Sasson Sassoni", "Mercedes" , 50000);
    CWorker Default("Default Session");

    Sasson.showWorker(cout);
    cout << '\n';
    Default.showWorker(cout);
}

But that's a lesson that should be learned in the trenches, not in school. Now, you might ask why the aliases refer to m_pCar instead of simply using the constructor parameters that were used to initialize m_pCar. The reason is you don't know the lifetime of those objects; it might be significantly shorter than the lifetime of the CWorker object. However, m_pCar lives as long as the CWorker object does, so it's safe to reference.

Note that I put all of this into a single file, but you can easily break it up into headers. It's important to recognize that header inclusion is textual, so you end up with a single file (a compiler-generated "translation unit) after all of the headers are merged into your source file. So starting out with a single file and then breaking it up is a good way to visualize your code's structure.

And now a few nits about your code:

#ifndef _CCar_H

Names beginning with an underscore and then an upper case letter are always reserved to the compiler. You shouldn't use them even if the name is extremely unlikely to be used by the compiler, simply as good practice. However, while _CCar_H is reserved, CCar_H is not, so this is an easy potential bug to fix.

CCar(const char *firma='\0',int price=0);

'\0' is not a pointer, so it's not a valid default value for the parameter. If you want an empty string, "" works (all of my examples above do this).

CCar::CCar(const char *firma, int price):m_price(price)
{
    strcpy(m_firma,firma);
}

You might consider checking the length of the parameter before trying to copy. strcpy() doesn't do any bounds checking, and will happily overflow m_firma if firma is longer than your array. Something like this would work:

#include <string.h>
#include <stdexcept>

CCar::CCar(const char *firma, int price):m_price(price)
{
    // Don't forget to consider the null character at the end too
    if (strlen(firma) > LEN_N_FIRMA - 1)
        throw std::invalid_argument("Parameter length error (too long)");

    strcpy(m_firma,firma);
}
CWorker::CWorker(const char *name,const char *firma,int price,int numOfChildren):m_numChildren(numOfChildren)
{
    strcpy(m_pCar->m_firma,firma);
    m_pCar->m_price=price;
    strcpy(m_name,name);
    m_pCar= new CCar();
    assert(m_pCar);
}

This code is totally backwards. You need to allocate memory to your pointer first, then dereference it:

CWorker::CWorker(const char *name,const char *firma,int price,int numOfChildren):m_numChildren(numOfChildren)
{
    // Allocate memory first
    m_pCar = new CCar();

    // Now use that memory
    strcpy(m_pCar->m_firma,firma);
    m_pCar->m_price=price;

    // Initialize other non-pointer members
    strcpy(m_name,name);
}

Note that using assert() to check your pointers is an exceptionally bad idea. assert() is intended to be used as a sanity check which catches programmer errors, not errors that could happen in a final release. Further, without the nothrow variation of new , a failed allocation will throw a std::bad_alloc exception rather than return a null pointer.

void main()

main() is required to return int in a hosted environment. While some compilers (such as Visual C++, which you're currently using) support returning void as an extension, it's generally unwise to do so.

The traditional excuse for returning void is to avoid the return statement, but in standard C++ that excuse is rendered moot because main() will automatically return 0 if execution falls off the end. These two definitions of main are functionally equivalent:

int main()
{
    // No return statement
}
int main()
{
    return 0;
}

Note that this applies only to main(). Failing to return a value in any other function with a non-void return type will result in undefined behavior (the kiss of death in C++).

thanks alot..i fixed it :), one more question

CWorker::CWorker(const char *name,const char *firma,int price,CChild A[],int numOfChildren):m_numChildren(numOfChildren)
{
	int i;
	strcpy(m_name,name);
	m_pCar= new CCar();
	assert(m_pCar);
	strcpy(m_pCar->m_firma,firma);
	m_pCar->m_price=price;
//	for(i=0;i<m_numChildren;i++)
//		m_cArr[i]=A[i];
}

in CWorker.h:

#pragma once

#include "CCar.h"
#include "CChild.h"

#define LEN_N_W 20
#define LEN_C 10

class CWorker
{
	char m_name[LEN_N_W];			// worker's name
	CCar  *m_pCar;							// car
	CChild m_cArr[LEN_C];				// array of children
	int m_numChildren;						// number of children to this worker
//	???  m_totalNumChildren;				// counter of all children of all workers
public:
	CWorker(const char*name="\0",const char *firma="\0",int price=0,CChild A[]=CChild(),int numOfChildren=0);
	~CWorker();	
	void showWorker()const;

};

new i have to do a defult for CChild A[]
CChild.h:

#pragma once
#define LEN_N_C 20


class CChild
{
	char m_name[LEN_N_C];		// a child name
	int m_age;								// a child age
public:
	CChild(const char *name="\0",int age=0);
};

how i can do it???

We're getting into sticky areas that I wouldn't recommend, but you could do it like this:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>

class foo {
    static int a_default[2];
    
    int _a[2];
public:
    foo(int init[2] = a_default)
    {
        std::copy(init, init + 2, _a);
    }
    
    friend std::ostream& operator<<(std::ostream& out, const foo& obj)
    {
        std::copy(obj._a, obj._a + 2, std::ostream_iterator<int>(out, " "));
        return out;
    }
};

int foo::a_default[2] = {0, 0};

int main()
{
    int init[2] = {1, 2};
    foo a, b(init);
    
    std::cout << a << '\n' << b << '\n';
}

how i can do a defult for CChild A[]...what's the syntecs?
is it : CCild A[]={CChild ("\0",0)}??...

no, i'm sorry i cant do it with Operator..and not with a static one..

i'm sorry i cant do it with Operator

The overloaded operator<< was boilerplate for my example. You don't need to include it. Since you're so opposed to extracting the necessary information from a complete example, I'll pare it down the the bare bones and let you figure out the rest:

class foo {
    static int a_default[2];

    int _a[2];
public:
    foo(int init[2] = a_default);
};
 
int foo::a_default[2] = {0, 0};

I apologize for being nice and offering a test driver to help you out. :icon_rolleyes:

and not with a static one..

You must have an object to use as the default argument, there's no getting around that. It's static to the CWorker class, global (relative to CWorker), or you don't use a default argument. Your choice. C++ doesn't support anonymous arrays.

i still dont have a clue...because
i have CWorker.h:

#pragma once

#include "CCar.h"
#include "CChild.h"

#define LEN_N_W 20
#define LEN_C 10

class CWorker
{
    char m_name[LEN_N_W];           // worker's name
    CCar  *m_pCar;                          // car
    CChild m_cArr[LEN_C];               // array of children
    int m_numChildren;                      // number of children to this worker
//  ???  m_totalNumChildren;                // counter of all children of all workers
public:
    CWorker(const char*name="\0",const char *firma="\0",int price=0,CChild A[]=CChild(),int numOfChildren=0);
    ~CWorker(); 
    void showWorker()const;

};

and i cant chanage it
and my mian is:

void main()
{
    CCar car("Mercedes" , 50000);
    CWorker *Sasson  = new CWorker("Sasson Sassoni");
    assert(Sasson);
    Sasson->showWorker();
    CChild A[] = { CChild("Shilgi1" , 1) , CChild("Shilgi2" , 2) , CChild("Shilgi3" , 3) };
    CWorker Shilgiya("Shilgiya" , "Fiat" , 22000   , A   ,  3);
    Shilgiya.showWorker();

and i must not change the class CWorker
i appriciat your help :)

void main()
{
CCar car("Mercedes" , 50000);
CWorker *Sasson  = new CWorker("Sasson Sassoni");
assert(Sasson);
Sasson->showWorker();
CChild A[] = { CChild("Shilgi1" , 1) , CChild("Shilgi2" , 2) , CChild("Shilgi3" , 3) };
CWorker Shilgiya("Shilgiya" , "Fiat" , 22000   , A   ,  3);
Shilgiya.showWorker();

and i must not change the class CWorker
i appriciat your help :)

and i must not change the class CWorker
i appriciat your help :)

Edited 3 Years Ago by Nick Evan: Fixed formatting

i think i did it,...one more question
i have the main.cpp:

#include <iostream>
#include <assert.h>
#include "CCar.h"
#include "CChild.h"
#include "CWorker.h"

using namespace std;

void addChild(CWorker a,const CChild&child);
void main()
{
	CCar car("Mercedes" , 50000);
	CWorker *Sasson  = new CWorker("Sasson Sassoni");
	assert(Sasson);
	Sasson->showWorker();
	addChild(*Sasson, CChild("Sassoniile", 3));
	addChild(*Sasson, CChild("Sassonchick", 7));
//	Sasson->setCar("Mercedes", 900000);
	Sasson->showWorker();
	cout<<"======================\n" << endl;
}
void addChild(CWorker a,const CChild&child)
{
	int i;
	for(i=0;i<m_numChildren;i++);					
		m_cArr[i]=child;					
	m_numChildren++;					
}

and the CWorker.h:

#pragma once

#include "CCar.h"
#include "CChild.h"

#define LEN_N_W 20
#define LEN_C 10

class CWorker
{
	char m_name[LEN_N_W];			// worker's name
	CCar  *m_pCar;							// car
	CChild m_cArr[LEN_C];				// array of children
	int m_numChildren;						// number of children to this worker
//	???  m_totalNumChildren;				// counter of all children of all workers
	friend void addChild(CWorker a,const CChild&child);
public:
	static CChild a[1];
	CWorker(const char *name="\0",const char *firma="\0",int price=0,CChild A[1]=a,int numOfChildren=0);
	~CWorker();	
	void showWorker()const;
	


};

and the compiler say it cant find m_numChildren,cArr...why this Addchild function doesnt see the privet of CWorker ???

nay way thanks a lot, i managed my self :),thank you Narue, you helped me alot :)

This article has been dead for over six months. Start a new discussion instead.