I am running Dev-C++ 4.9.9.2 with XP.
I am obtaining a multiple def build error for a private static object. This obj is only declared in the mySeq.hpp file, once in the private section of the class's scope and once after the class's scope. (Omitting this definition outside the scope produces the expected error.)
In addition to this error I have a related question. I assume it good practice to add to the class a means of releasing the storage on the heap created by the class's private static objects. If so, would using the setDefault member to delete the data and set the object's pointer to NULL be a good idea? Or, is it considered better to add another static member that deletes the static object's data and sets the pointer to NULL?
mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
testStatic.o(.bss+0x0):testStatic.cpp: first defined here
collect2: ld returned 1 exit status
make.exe: *** [testStatic.exe] Error 1
Execution terminated
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
private:
int size;
double* data;
static mySeq defaultSeq;
};
mySeq mySeq::defaultSeq;
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2008-09-29
In relation with your's first question, IMHO you can not declare that static member.
static mySeq defaultSeq;
Here defaultSeq is a mySeg objetc type, and there are a circular definition; mySeg class is defined inside the definition. You can use a pointer to mySeg there but not mySeg itself.
HTH.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
In the header file, you create an instance of mySeq::defaultSeq in every module that includes the header, so the linker sees more than one. That line should be moved to MySeq.cpp so there is only one instance.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I tried moving this statement as you suggested. The results (see below) produced a similar error. I have written "self referential" declarations and definitions successfully before. And, this program does run well if all modules are placed in one .cpp file.
Compiler: Default compiler
Building Makefile: "C:\CPP\test\Makefile.win"
Executing make...
make.exe -f "C:\CPP\test\Makefile.win" all
g++.exe testStatic.o mySeq.o -o "testStatic.exe" -L"C:/Dev-Cpp/lib"
mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
testStatic.o(.bss+0x0):testStatic.cpp: first defined here
collect2: ld returned 1 exit status
make.exe: *** [testStatic.exe] Error 1
Execution terminated
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
mySeq(const mySeq&);
mySeq& operator=(const mySeq&);
private:
int size;
double* data;
static mySeq defaultSeq;
};
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq mySeq::defaultSeq;
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
mySeq::mySeq(const mySeq& v)
{
data = new double [size=v.size];
for (int i=0; i<v.size; i++) data[i] = v.data[i];
}
mySeq& mySeq::operator=(const mySeq& v)
{
if (this != &v) //if addr of lhs = addr of rhs, then do nothing
{ //cannot use for static obj, has no this pointer
if (size != v.size)
{
delete [] data;
data = 0;
data = new double [size=v.size];
}
for (int i=0; i<v.size; i++) data[i]=v.data[i];
}
return *this;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
Clifford had the correct observation. So this current problem might meet your request. See the following .hpp for the class, .cpp for the class, and main.
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
mySeq(const mySeq&);
mySeq& operator=(const mySeq&);
private:
int size;
double* data;
static mySeq defaultSeq;
};
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq mySeq::defaultSeq;
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
mySeq::mySeq(const mySeq& v)
{
data = new double [size=v.size];
for (int i=0; i<v.size; i++) data[i] = v.data[i];
}
mySeq& mySeq::operator=(const mySeq& v)
{
if (this != &v) //if addr of lhs = addr of rhs, then do nothing
{ //cannot use for static obj, has no this pointer
if (size != v.size)
{
delete [] data;
data = 0;
data = new double [size=v.size];
}
for (int i=0; i<v.size; i++) data[i]=v.data[i];
}
return *this;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
That log only shows the linker stage, so nothing was re-compiled, only a re-link of previously compiled modules. Although of course this may not have been your first build since the change. Do a "Rebuild All" before posting the log.
My guess is in fact that you have incomplete file dependencies in the project makefile and that testStatic.cpp was never recompiled when MySeq.hpp changed, so it still contains the old static instance. If that is the case, the Rebuild All will solve the problem, but you should switch off Dev-C++'s "Fast but imperfect dependency generation" mode - it does not work, and besides that on a small project, complete dependencies do not take long to generate, and on a large project that are essential.
It would be useful when posting multiple source file content if you could put some sort of separator between them!
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am running Dev-C++ 4.9.9.2 with XP.
I am obtaining a multiple def build error for a private static object. This obj is only declared in the mySeq.hpp file, once in the private section of the class's scope and once after the class's scope. (Omitting this definition outside the scope produces the expected error.)
In addition to this error I have a related question. I assume it good practice to add to the class a means of releasing the storage on the heap created by the class's private static objects. If so, would using the setDefault member to delete the data and set the object's pointer to NULL be a good idea? Or, is it considered better to add another static member that deletes the static object's data and sets the pointer to NULL?
Thank you,
Dick
Compiler: Default compiler
Building Makefile: "C:\CPP\test\Makefile.win"
Executing make...
make.exe -f "C:\CPP\test\Makefile.win" all
g++.exe -c mySeq.cpp -o mySeq.o -I"C:/Dev-Cpp/lib/gcc/mingw32/3.4.2/include" -I"C:/Dev-Cpp/include/c++/3.4.2/backward" -I"C:/Dev-Cpp/include/c++/3.4.2/mingw32" -I"C:/Dev-Cpp/include/c++/3.4.2" -I"C:/Dev-Cpp/include"
g++.exe testStatic.o mySeq.o -o "testStatic.exe" -L"C:/Dev-Cpp/lib"
mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
testStatic.o(.bss+0x0):testStatic.cpp: first defined here
collect2: ld returned 1 exit status
make.exe: *** [testStatic.exe] Error 1
Execution terminated
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
private:
int size;
double* data;
static mySeq defaultSeq;
};
mySeq mySeq::defaultSeq;
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
}
In relation with your's first question, IMHO you can not declare that static member.
static mySeq defaultSeq;
Here defaultSeq is a mySeg objetc type, and there are a circular definition; mySeg class is defined inside the definition. You can use a pointer to mySeg there but not mySeg itself.
HTH.
By placing teh declaration:
mySeq mySeq::defaultSeq;
In the header file, you create an instance of mySeq::defaultSeq in every module that includes the header, so the linker sees more than one. That line should be moved to MySeq.cpp so there is only one instance.
Clifford
I tried moving this statement as you suggested. The results (see below) produced a similar error. I have written "self referential" declarations and definitions successfully before. And, this program does run well if all modules are placed in one .cpp file.
Compiler: Default compiler
Building Makefile: "C:\CPP\test\Makefile.win"
Executing make...
make.exe -f "C:\CPP\test\Makefile.win" all
g++.exe testStatic.o mySeq.o -o "testStatic.exe" -L"C:/Dev-Cpp/lib"
mySeq.o(.bss+0x0):mySeq.cpp: multiple definition of `mySeq::defaultSeq'
testStatic.o(.bss+0x0):testStatic.cpp: first defined here
collect2: ld returned 1 exit status
make.exe: *** [testStatic.exe] Error 1
Execution terminated
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
mySeq(const mySeq&);
mySeq& operator=(const mySeq&);
private:
int size;
double* data;
static mySeq defaultSeq;
};
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq mySeq::defaultSeq;
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
mySeq::mySeq(const mySeq& v)
{
data = new double [size=v.size];
for (int i=0; i<v.size; i++) data[i] = v.data[i];
}
mySeq& mySeq::operator=(const mySeq& v)
{
if (this != &v) //if addr of lhs = addr of rhs, then do nothing
{ //cannot use for static obj, has no this pointer
if (size != v.size)
{
delete [] data;
data = 0;
data = new double [size=v.size];
}
for (int i=0; i<v.size; i++) data[i]=v.data[i];
}
return *this;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
}
>> I have written "self referential" declarations and definitions successfully before.
Would you show an easy example of that? I mean a self reference to the class, not a pointer to the class.
Thanks in advance.
Clifford had the correct observation. So this current problem might meet your request. See the following .hpp for the class, .cpp for the class, and main.
ifndef MYSEQ_HPP
define MYSEQ_HPP
class mySeq
{
public:
mySeq(const int n=0, const double* const d=0);
~mySeq() { delete [] data; data = 0; }
mySeq(const mySeq&);
mySeq& operator=(const mySeq&);
private:
int size;
double* data;
static mySeq defaultSeq;
};
endif
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
mySeq mySeq::defaultSeq;
mySeq::mySeq(const int n, const double* const d)
{
size = n ? n : defaultSeq.size;
if ( size>0 )
{
data = new double [size];
if (n==0)
{
for (int i=0; i<size; i++) data[i] = defaultSeq.data[i];
}
else
{
for (int i=0; i<size; i++) data[i] = d[i];
}
}
else data = 0;
}
mySeq::mySeq(const mySeq& v)
{
data = new double [size=v.size];
for (int i=0; i<v.size; i++) data[i] = v.data[i];
}
mySeq& mySeq::operator=(const mySeq& v)
{
if (this != &v) //if addr of lhs = addr of rhs, then do nothing
{ //cannot use for static obj, has no this pointer
if (size != v.size)
{
delete [] data;
data = 0;
data = new double [size=v.size];
}
for (int i=0; i<v.size; i++) data[i]=v.data[i];
}
return *this;
}
void mySeq::setDefault(const int sz, const double* const d)
{
defaultSeq.size = sz;
if (defaultSeq.data != 0)
{
delete[] defaultSeq.data;
defaultSeq.data = 0;
}
if (sz>0)
{
defaultSeq.data = new double [sz];
for (int i=0; i<sz; i++) defaultSeq.data[i]=d[i];
}
}
void mySeq::writeSeq() const
{
if (size>0)
{
for (int i=0; i<size; i++)
{
std::cout << i << '\t' << data[i] << '\n';
}
}
std::cout << '\n';
}
include <cstdlib>
include <iostream>
include <cmath>
include "mySeq.hpp"
int main(int argc, char *argv[])
{
int ndefault=3;
double d[] = {1., 1., 1.};
}
That log only shows the linker stage, so nothing was re-compiled, only a re-link of previously compiled modules. Although of course this may not have been your first build since the change. Do a "Rebuild All" before posting the log.
My guess is in fact that you have incomplete file dependencies in the project makefile and that testStatic.cpp was never recompiled when MySeq.hpp changed, so it still contains the old static instance. If that is the case, the Rebuild All will solve the problem, but you should switch off Dev-C++'s "Fast but imperfect dependency generation" mode - it does not work, and besides that on a small project, complete dependencies do not take long to generate, and on a large project that are essential.
It would be useful when posting multiple source file content if you could put some sort of separator between them!
Clifford
Right you are. It works fine now. Someday I just might get the hang of this IDE. I appreciate you patience.
Dick