Sign in to follow this  
jujumbura

c++ compile error ( copy constructor )

Recommended Posts

Hello all, Visual Studio is giving me an error when I am attempting to push_back() an instance of my TestPolyData class onto a vector. The error message is: c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\vector(810): error C2558: class 'TestPolyData' : no copy constructor available or copy constructor is declared 'explicit' I am not sure why it is giving me this. I do have a copy constructor, and it is a public method. I don't have anything declared 'explicit', I am not sure what that means. Has anyone seen this before, or know what might be causing my issue? The header for TestPolyData is below.



#ifndef TESTPOLYDATA_H 
#define TESTPOLYDATA_H

#include "Common.h"

struct SATINTERVAL
{
	bool collisionExists;	// if this is false, then we don't care about the other data
	bool collisionInfinite;  // this is true in cases where the shapes will never collide, or will alawys collide
	float intervalLow;	// this is the smallest value where the shapes collide( or sometimes, the smallest extent along an axis )
	float intervalHigh;		// this is the largest value where the shapes collide( or sometimes, the largest extent along an axis )
	D3DXVECTOR3 lastAxisPassed;	// this axis is the normal of the final plane of separation crossed before the shapes start to overlap

	/// test data
	int collideAttemptNum;	// used for enumerating collision attempts in log data
	///
};

class TestPolyData
{

public:
	
	TestPolyData( D3DXVECTOR3 points[], int pointCount, D3DXVECTOR3 edges[], int edgeCount, D3DXVECTOR3 normal );
	TestPolyData( TestPolyData &orig );
	~TestPolyData();
	SATINTERVAL SATPolyPolyMinDist( TestPolyData &sourcePoly, D3DXVECTOR3 &motionDir, int collideAttemptNum=0 );
	void printInputs( TestPolyData &sourcePoly, int collideAttemptNum );
	

private:

	SATINTERVAL SATTestSepPlane( TestPolyData &sourcePoly, D3DXVECTOR3 &planeNormal, float motionNormalComponent );
	SATINTERVAL planeExtentMinMax( D3DXVECTOR3 &planeNormal );
	SATINTERVAL intervalIntersection( SATINTERVAL &interval1, SATINTERVAL &interval2 );
	SATINTERVAL intervalUnion( SATINTERVAL &interval1, SATINTERVAL &interval2 );

	D3DXVECTOR3 *m_pPoints;
	int m_PointCount;
	D3DXVECTOR3 *m_pEdges;
	int m_EdgeCount;
	D3DXVECTOR3 m_Normal;

	/// test data
	std::ofstream outfile2;
	///

};

#endif // !defined( TESTPOLYDATA_H )

Share this post


Link to post
Share on other sites
The reference parameter to your copy constructor needs to be const. The copy operation is not supposed to modify the object being copied, and in some cases a mutable (non-const) object is not available; so the requirement is for a const reference.

Share this post


Link to post
Share on other sites
Thanks, that solved that error.

Although it looks like being an insertable type into a vector requires quite a few other defined functions that I don't have. =, !=, etc.

I may want to look at another way of storing instances of my class =(

Share this post


Link to post
Share on other sites
Quote:
Original post by jujumbura
Although it looks like being an insertable type into a vector requires quite a few other defined functions that I don't have. =, !=, etc.


The only requirements on a type T used to instatiate a std::vector is that T is CopyConstructible and Assignable. If the implementation of std::vector has any other requirements other than those explcitily state in section 23.1 of the standard, you need to toss it out and find a conforming implementation.

Share this post


Link to post
Share on other sites
Your problem is your member std::ofstream variable. std::ofstream is non-copyable (what would it mean to open a file for writing and write something to it, then make a copy of the file and write different data to the original and the copy?) and thus the compiler is unable to generate a default copy-constructor and copy-assignment operator. Prefer to hold your std::ofstream member by (smart) pointer instead of by value.

Σnigma

Share this post


Link to post
Share on other sites
Better yet, prefer not to hold it as a member at all. This doesn't appear to be any kind of logging class, so presumably you only need the stream for some kind of serialization function - in which case you should declare a local within that function (being given a filename) or accept one as a parameter - or better yet, do your outputting idiomatically by overloading the free-function operator<<:


// The usually recommended way
friend ostream& operator<<(ostream& os, const TestPolyData& tpd) {
// output members of tpd to os here...
return os;
}

// You can avoid the need for a 'friend' declaration by re-implementing it in
// terms of a member function. Now you have an extra way of doing things, but
// wrote correspondingly extra code. The encapsulation/"good OO practice"
// benefits here are highly controversial either way...
void TestPolyData::printTo(ostream& os) const {
// output members of tpd to os here...
}

ostream& operator<<(ostream& os, const TestPolyData& tpd) {
tpd.printTo(os);
return os;
}

// With either of these approaches, users can now do 'cout << myTestPoly' for
// example - or similarly with an already-opened file stream, etc.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this