|
Hi,
Thanks for replying!
Actually, no, that's not what I'm trying to do. I make use of the pointer x within the methods f, g, and h, but I also use other variables which are INT's in all cases (that is, no matter whether x is an INT*, FLOAT*, etc.). So it doesn't really matter whether T shows up again in the class definition.
Also, I actually do have implementations for all of the class methods in my code, I just showed one (g) to make my question shorter.
I happened to post another message at the same time you were posting this one, in which I say my problem may be due to a need for explicit instantiation because my classes are in a static library.
Thank you for your suggestions!
|
|
|
|
|
Californian2 wrote: I happened to post another message at the same time you were posting this one, in which I say my problem may be due to a need for explicit instantiation because my classes are in a static library.
You mean you have provided implementation in some other CPP file (and created as static library)?
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
My template class and the classes which are derived from it are declared in a .h file, and the implementation (including the method, g, which I showed in my question) is done in a separate .cpp file. These files are part of a static library.
I have a separate application which uses the classes from the library. When I link the application, I get the errors I mentioned.
|
|
|
|
|
There it is!!!
If I properly understood you question, C++ not allows you to separate declaration and definition of template methods.
Please See C++ FAQ[^]
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
Yeah, I've heard that too. I did get it to work with separate declaration and definition files in the end, though, so maybe that information is outdated now?
It turned out I needed to use explicit instantiation in my library. In my .cpp file, I added the line:
template class Base<INT>;
I wrote a longer explanation in a news item, below.
Thank you!
|
|
|
|
|
I neglected to mention that my template class and derived class are in a static library, so possibly the problem is that I need to do explicit instantiation of the template class.
However, using template class Base<INT>; gives me warning C4661, no suitable definition provided for explicit template instantiation request.
How do I explicitly instantiate a template class in a library?
|
|
|
|
|
It turns out that using template class Base<INT>; is the answer after all.
For anyone else out there with the same question, here is what finally worked for me. In a .h file, the template class and derived class are declared as follows:
template <class T>
class Base {
public:
Base();
Base(INT);
virtual ~Base();
virtual INT f();
virtual INT g(INT);
INT n;
T* x;
};
class Derived : public Base<INT> {
public:
Derived(): Base() {};
Derived(INT): Base() {};
~Derived();
INT h(FLOAT);
};
The implementation is done in a separate .cpp file. Use explicit instantiation, that is, use the following line in that file:
template class Base<INT>;
and for the template class methods, use:
template <class T> INT Base<T>::f()
{
// (code here)
}
template <class T> INT Base<T>::g(INT num)
{
// (code here)
}
The derived class methods use the usual syntax for any class method.
That's it!
As a side note, the compiler and linker don't complain (and the application runs fine) if I declare the template class methods using either virtual INT Base<T>::g(INT); or virtual INT g(INT); , that is, if the class declaration is either:
template <class T>
class Base {
public:
// CONSTRUCTORS:
Base();
Base(INT);
// DESTRUCTOR:
virtual ~Base();
// METHODS:
virtual INT Base<T>::f();
virtual INT Base<T>::g(INT);
// DATA:
INT n;
T* x;
};
or:
template <class T>
class Base {
public:
Base();
Base(INT);
virtual ~Base();
virtual INT f();
virtual INT g(INT);
INT n;
T* x;
};
I don't know where I picked up the syntax for the first version, though, so I used the second version in the end.
Thanks to those who made comments!
|
|
|
|
|
Hi, I'm trying to map a network storage drive by using the following code:-
NETRESOURCE NetResource;
NetResource.dwType = RESOURCETYPE_ANY; //RESOURCETYPE_DISK;
NetResource.lpRemoteName = "\\\\STORAGE-93F8\\PUBLIC";
NetResource.lpLocalName = "Z:";
DWORD dwRC;
dwRC = WNetAddConnection2(&NetResource,"","",0);
This gives a return code of 487 which is obviously an error but I can't a definmition for it - some references on the 'net imply resource not found. In a cmd window, I can issue "net use z: \\STORAGE-93F8" and this is successful. So what's wrong with the call to WNetAddConnection ? Any help appreciated !
Doug
|
|
|
|
|
|
Hello to all, Sorry for posting such question here but couldn't find any more suitable place on
CodeProject, and I have no intention of posting to any other forum!!!!!!!!
the problem is as follows.
I have an application to calculate the results of a square polynom:
#include<iostream.h>
#include<math.h>
void equall(int a,int b,int c)
{
float x1;
x1=(-b/(2*a));
cout<<"there is only one root and it's: x1="<<x1<<".\n";
}
void equall(int a,int b,int c)
{
float x1, delta;
delta=0;
x1= (-b+delta)/(2*a);
cout<<"there is only one root and it's: x1="<<x1<<".\n";
}
void bigger(int a,int b,int c)
{
float x1,x2,delta;
delta=sqrt((b*b)-(4*a*c));
x1=(-b-delta)/(2*a);
x2=(-b+delta)/(2*a);
cout<<"the two roots are x1="<<x1<<" and x2="<<x2<<".\n";
}
void main()
{
int a,b,c;
float delta;
cout<<"enter 3 variables (a,b,c) for the square equation: (the integer of the number is the one that counts) ";
cin>>a>>b>>c;
delta=((b*b)-(4*a*c));
if(delta<0)
cout<<"the square roots,x1 and x2,doesn't exist!\n";
if(delta==0)
equall(a,b,c);
if(delta>0)
bigger(a,b,c);
}
</math.h></iostream.h>
So it's like that, if I use version 1 x1 always gets a value of 0 no metter what I put
into a, b, c. this is of course not correct!!!
if I use version 2 it's acting OK.
this behavior is weird to me, I can't seem to understand what is it deriving from.
|
|
|
|
|
Hi,
I've had some problems like this sometimes. In your version 1, all of the variables on the right-hand side are integers, so the division is done using all integers (even though on the left-hand side you have a float), and any result less than 1 gets rounded down to 0 before being placed in x1. In your version 2, you use a variable of type float (the variable called delta) on the right-hand side as well, so the division is done using floats and a non-integer value can now be placed in x1.
You can fix it by using either:
x1 = (float)(-b)/(2*a);
or
x1 = -b/(2.0f*a);
It is weird, but I've seen it before!
modified on Wednesday, December 26, 2007 7:30:08 PM
|
|
|
|
|
oh man thanks, so stupid of me not to notice that,
you really helped me.
thank you very much.
|
|
|
|
|
You're welcome!
|
|
|
|
|
Good, just a note:
Californian2 wrote: x1 = (float)(-b)/(2*a);
brackets around -b have no effect. On the other hand you're relying on higher precedence of cast operator with respect of the division one, nothing wrong with that, but maybe
x1 = ((float)-b)/(2*a);
better illustrates what are you doing.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
Hi,
you should not have ints at all in this program; I suggest you use floats or better
yet doubles for all coefficients, delta, x, etc. It simply is not an integer problem,
it is a real (or complex) problem.
If you want to deal with the delta<0 case, have a look at some CodeProject articles
on complex classes.
|
|
|
|
|
When using float and double types, it's a good idea to not use integer constants. In other words, use 0.0 and 2.0 instead of 0 and 2 so that the math library is loaded and initialized properly.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Gents,
is it possible to somehow 'receive' the data from another program and it's Listbox control ?
|
|
|
|
|
|
Yes if you have a handle to that window of program you can get data of lists.
|
|
|
|
|
Hello everyone,
Here is a sample from Dr. Dobb C++. In the analysis, the code is bad below.
But I do not think the code is bad,
1. if bad_alloc is thrown in new int[], we just catch it and write some log;
2. if there are any exception in B's constructor, we will also be in catch block and we could also write some log.
Why it is bad code? Any comments?
(I do not agree that there is resource leak, since if we met with bad_alloc in new int[], there is no memory allocated at all, so no root of memory/resource leak).
http://www.ddj.com/cpp/184401297
C::C(int)
try
: B(new int[n])
{
...
}
catch(Error &e)
{
}
thanks in advance,
George
|
|
|
|
|
IMHO the problem is: if something go wrong inside B constructor the will reach the catch block, where there is no chance to release the acquired resource (i.e. allocated memory).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|
Hi CPallini,
I think you mean the memory allocation of new int[] is successful, but in somewhere in constructor, there is an exception, right?
I think in this case, we can use a catch block in B's constructor to invoke delete[] to free memory, and then re-throw the exception to constructor of class C.
Any comments? Please feel free to correct me if I am wrong.
regards,
George
|
|
|
|
|
My doubt is that, if B swallow the exception in its ctor, how C can know that same? B will be partially constructed without knowing that, C completed it's initialization. Those who using the class, C misunderstand that the whole construction was successful and will start using partially constructed objects. I think the error handling can't be done properly if we approach this method. Correct me if I'm wrong.
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
Hi Sarath,
If there are any exception in B's constructor, the exception will be thrown to C's constructor. Why do you say,
Sarath. wrote: B will be partially constructed without knowing that, C completed it's initialization.
and,
Sarath. wrote: misunderstand that the whole construction was successful and will start using partially constructed objects.
regards,
George
|
|
|
|
|
Suppose you cannot change B class, B constructor hasn't a catch block able to face such a situation (after all B class doesn't even know that memory is allocated on the heap), and C class cannot access B internal data (OOP information hiding, he he ).
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
[my articles]
|
|
|
|
|