class DemodNyqCell
{
vector<NyqMultBlock> blocks;
int32_t sum;
int32_t resetValue;
public:
When an object of type DemodNyqCell is created, I want to create a vector of NyqMultBlock elements, and initialize them. They won't all be initialized the same.
And, I can't remember how to code the constructor to give me access to the member objects' constructor. Can someone jog my memory?
Google "initialization list". Though that isn't too useful here. You'll be able to call vector's constructor, but not its elements. You should instead do
Thanks, hamsterman. I assume you mean like this (I didn't put in any of the changing parameters here, to keep the example simple):
1 2 3 4 5 6 7 8
DemodNyqCell::DemodNyqCell(int32_t rv) // default constructor
: sum(rv), resetValue(rv)
{
for (int i = 0; i <= DEMOD_NYQ_NBR_BLOCKS; ++i)
{
blocks.push_back(NyqMultBlock(rv, false));
}
}
That compiles, so I'm halfway home. Now, I need to do something different in my copy constructor, because of the const member of NyqMultBlock. I'm accustomed to writing copy constructors like this:
1 2 3 4 5 6 7 8 9
DemodNyqCell::DemodNyqCell // copy constructor
(const DemodNyqCell &dnc)
{
for (int i = 0; i <= DEMOD_NYQ_NBR_BLOCKS; ++i)
{
blocks.at(i) = dnc.blocks.at(i);
sum = dnc.sum;
}
}
but the compiler is telling me I can't use the default assignment operator. What am I doing wrong here?
OK, now that I'm looking at with rested eyes, I can see that this wouldn't work, because the vector elements haven't been created. So, now I tried this:
1 2 3 4 5 6 7 8 9 10 11 12
DemodNyqCell::DemodNyqCell // copy constructor
(const DemodNyqCell &dnc)
{
blocks.reserve(DEMOD_NYQ_NBR_BLOCKS);
for (int i = 0; i <= DEMOD_NYQ_NBR_BLOCKS; ++i)
{
// blocks.at(i) = dnc.blocks.at(i);
blocks.push_back(NyqMultBlock(dnc.blocks.at(i).getResetValue(),
dnc.blocks.at(i).getDelay()));
sum = dnc.sum;
}
}
which seems like it should work, but I'm getting a compiler error (actually two). Here's the first:
error: passing 'const NyqMultBlock' as 'this' argument of 'int32_t NyqMultBlock::getResetValue()' discards qualifiers
Anyone want to tell me what this means, and maybe what I'm doing wrong? Constructors are still a bit of a mystery to me.
Now, I need to do something different in my copy constructor, because of the const member of NyqMultBlock
Nope. Every member will be created with its own copy constructor. The constant member will be a copy of the other constant member.
The problem arises if you have something without a copy constructor, like a stream or a reference. (or if the copy is no good, like with pointers)
getResetValue() discards qualifiers
That means that your method is not const correct. in the copy constructor you are passing a constant object, so you can only use constant methods
1 2 3 4
class foo{
public:
void bar() const; // it can be used with constant objects
};
By the way, it is a good idea to reserve() in order to avoid reallocations.
I commented out the "const" on my member variable, because I was getting some other errors I didn't want to deal with at the time. So, I don't think that's the problem; the only place I use "const" is in the copy constructors.
ne555: I'm sorry, but I'm not following you on this. Are you saying I need to declare my copy constructor as const? And again, I've removed (temporarily) the const modifier from my member declaration.
error: passing 'const NyqMultBlock' as 'this' argument of 'int32_t NyqMultBlock::getResetValue()' discards qualifiers
relates to your getResetValue method is not a const method - ie it does not have te const keyword after its definition - which implies that the method may change the state of the object.
In your copy constructor however, you are passing this as
const DemodNyqCell &dnc
this means that the entire dnc instance shouldn't change after te copy construction has taken place - however the call to:
dnc.blocks.at(i).getResetValue()
is potentially changing the respective element stored in dnc, hence is ultimately changing dnc which can't happen since it's const.
Thank you for the explanation, SIK. So what is the lesson here: that any function used in a copy constructor must be const? (Given that copy constructors are passed const pointers.)
Anyway, that compiled. Last thing to clean up: I returned the "const" qualifier to my member in the first post, and am back to getting this error with respect to my default constructor:
error: non-static const member 'const bool NyqMultBlock::delay', can't use default assignment operator
/usr/include/c++/4.2.1/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = NyqMultBlock, _Alloc = std::allocator<NyqMultBlock>]':
/usr/include/c++/4.2.1/bits/vector.tcc:256: note: synthesized method 'NyqMultBlock& NyqMultBlock::operator=(const NyqMultBlock&)' first required here
So, the compiler is telling me I need to make my own assignment operator, but I have a feeling that the real solution lies elsewhere. Any help would be appreciated. Thanks!
So what is the lesson here: that any function used in a copy constructor must be const?
Yep. But remember that you can access at the private data, as you are inside the class.
Also the default copy constructor is enough in most cases.
AFAIK, yes, you need to provide an assignment operator. Kinda sucks considering that you want a member to member copy.
But as after a = b; they may have different 'delay' value, makes sense.
On second thought ¿wtf is the STL doing?
1 2 3 4 5 6 7 8 9 10 11 12 13 14
template<typename _Tp, typename _Alloc>
void
vector<_Tp, _Alloc>::
_M_insert_aux(iterator __position, const _Tp& __x){
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage){ //¿what does this mean?
this->_M_impl.construct(this->_M_impl._M_finish, (*(this->_M_impl._M_finish - 1)) );
++this->_M_impl._M_finish;
_Tp __x_copy = __x; //¿what is this for?
std::copy_backward(__position.base(), this->_M_impl._M_finish - 2, this->_M_impl._M_finish - 1);
*__position = __x_copy; //using the assignment
}
OK, now I'm confused. (push_back) It is not using the assignment operator (that makes sense), ¿why is it asking it for?
All I'm trying to do is instantiate an object from within another object's constructor. It's hard to believe that I'd have to supply an operator for that.
Any ideas, anyone?
EDIT: just for fun, I created an assignment operator, and got the predictable error about trying to assign a read-only data-member (delay). So, that doesn't help; it only postpones the problem. Could it be that what I'm trying to do just isn't legal? Seems unlikely, but I don't know what else to try.
I changed some of the types for ease of compiling, but this should effectively still show what is important - unless I'm not understandng the issue correctly.
The assignment operator is required by stl's vector class since we are not storing pointers of NyqMultBlock but actual objects of that class - hence internally when the vector wants to set the object received in push_back call to it's allocated value internally it needs to have the [ = ] resolved for this class.
Hey, SIK: thanks for putting so much work into this. What you have above is essentially what I have, with the exception that you're using a #define instead of a const for the delay. (I was taught to avoid #defines, but that's another story for another time.) So...I take it, your version compiles? I guess it gets around the problem with the const assignment I'm trying to in the constructor.