|
Could someone tell me what is going on here? Please.
I am trying to output audio frequency using waveOutWrite. I am using callback function.
Works as expected.
Now I would like to output the audio using the “loop” parameter in the header.
The header sets WHDR_DONE flag when the loop is done.
Now I needed to “translate “ WHDR_DONE flag to the callabck WOM_DONE message for further processing .
I couldn't make the callback work on event so I used this.( I'll try it again).
<b>I have used this „event“ , it partially works but I have no idea why.</b>
HANDLE event;
event = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD dwWaitResult;
Callback function:
void CALLBACK C_AssynchPlay2::CallbackWaveOutProc(HWAVEOUT hwo,
UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
TRACE("\nvoid CALLBACK C_AssynchPlay2::CallbackWaveOutProc...");
if (uMsg == WOM_DONE)
{
AfxMessageBox("finished "); // gets here
return;
}
Output audio function:
bRC = TRUE;
TRACE("\nInitialize pcm %i ",i );
pcm[i].lFreq = Freq;
pcm[i].dDelay = 1; // Delay; must be < 1
pcm[i].whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
pcm[i].whdr.dwLoops = 5; // works
if(!pcm[i].C_CreateSinus())
TRACE("\nFailed pcm[i].C_CreateSinus() %i ", i );
HANDLE event;
event = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD dwWaitResult;
mmres = waveOutPrepareHeader(hwout, & pcm[i].whdr, sizeof(WAVEHDR));
if (mmres != MMSYSERR_NOERROR) {ASSERT(0); bOK = FALSE;}
mmres = waveOutWrite(hwout, & pcm[i].whdr, sizeof(WAVEHDR));
TRACE("\nWait event ");
dwWaitResult = WaitForSingleObject(event,INFINITE); //sets WOM_DONE in callback
From here this code never gets processed
TRACE("\nWait event OK ");
AfxMessageBox("Wait event.... ");
return bRC;
Many thanks for your help.
Cheers
Vaclav
|
|
|
|
|
Vaclav_Sal wrote: dwWaitResult = WaitForSingleObject(event,INFINITE); //sets WOM_DONE in callback
You're waiting for an event to be set for an infinite amount of time. I think that it's not returning because the event is never set, and as such the code doesn't progress further to execute your AfxMessageBox.
Have you verified that the WaitForSingleObject call actually returns?
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
That is my main question. When I comment the WaitForSingleObject out the WOM_DONE get set immediatelly after the waveOutWrite. Not waiting for the header loop flag to indicate completion of the loop. There is no mechanism to control that in that case.
It all indicates that the event never gets set as you pointed out.
I have not checked for memory leaks either, mainly beacause the CALLBACK process function gets terminated , for now.
I think I need to go back to try CALLBACK on event instead of just plain CALLBACK function.
|
|
|
|
|
In the case you've provided, the WaitForSingleObject will wait forever (due to the INFINITE time specification), or until the event that's it's waiting on to be "set". Ideally, you should be changing the state of this event in another thread, and the wait will end.
Are you performing everything in the same thread? That's not how it's intended to work.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Yes, it is all done in the same thread.
This callback function starts the audio process and "monitors" the completion of the audio buffer which is set to output about 1 second of audio.
mmres = waveOutOpen(&hwout, WAVE_MAPPER, &wfme,
(DWORD) CallbackWaveOutProc, 0x12345, CALLBACK_FUNCTION);
The issue is that I want to utilize "loop" feature of this audio buffer and output the audio for more then 1 second. Without the "wait for event" the waveOutWrite returns immediately after the audio output starts, setting the WOM_DONE in the callback function.
Inserting the wait for event let the waveOutWrite generate the WOM_DONE AFTER the WHDR_DONE is asserted.
I did write simple wait loop to monitor this WHDR_DONE flag and it worked, but I thought I could use Windows event to do same. It does what I want, but I just do not understand how it does it.
Vaclav
|
|
|
|
|
I want to write program which would completely wipe out my hard disk and the data on the hard disk should not be recoverable once wiped. I want to implement this in c/c++.
|
|
|
|
|
|
I would guess that the only totally wipe would be using "format".
Definitely not in favor of the above link "toy program".
|
|
|
|
|
Step 1: Backup your drives.
This is meant as a humorous reminder. Seriously, don't run a single test before you are sure you have a working backup.
Soren Madsen
"When you don't know what you're doing it's best to do it quickly" - Jase #DuckDynasty
|
|
|
|
|
There's an open source project called DBAN that does this...
http://www.dban.org/[^]
http://en.wikipedia.org/wiki/Darik's_Boot_and_Nuke[^]
Since it's open source, you should be able to look through the source to see how they accomplish this (if you're trying to learn). If you're just trying to blast some old disks, you can just download it and use it, it works VERY WELL (be careful).
|
|
|
|
|
There is no way to make data completely unrecoverable. But using some shredding algorithms you can slow down the process of recovery of the shredded(deleted) data.
|
|
|
|
|
The following question is about how to handle assignment operators (& copy constructors)
in a hierarchy of polymorphic objects in order to be able to work with all kind of assignments & copy:
i.e. we would ideally like to work always with base class pointers, but also allow to use
directly derived class pointers.
In fact I do present two techniques to deal with this argument:
A) The first does make use of "virtual" assignment operators
and, as far as I know, should be the "standard" way to deal with this argument in C++,
but it has the drawback that as soon as your hierarchy is more than one level deep
it leads to a combinatorial explosion of assignment operators.
This technique I call "Polymorphism A" in the following.
B) The second technique does make use of an aux virtual copy method,
using this aux virtual copy method fewer assignment operators have to be defined,
but it has the drawback that you cannot call directly the base class assignment op. from derived ones.
This technique I call "Polymorphism B" in the following.
My question is more like an open discussion: i.e. I do ask what are your opinions on both techniques,
what drawbacks you may see in them, and, eventually, if you do know of a better way to solve the same problem.
In the sample code I give objects are relatively simple, but keep in mind that we would like
to apply those techniques to complicated objects where "deep" copies are to be used.
Let us see the code:
------- Polymorphism A - hierarchy --------------------
#include "stdafx.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
using namespace std;
class CBase {
private:
CBase() { cout << "CBase() default ctor called" << endl;
_data = -1; _isvalid = false; };
public:
explicit CBase(const int data) { cout << "CBase(const int data) explicit ctor called" << endl;
_data = data; _isvalid = true; };
virtual ~CBase() { cout << "~CBase() dtor called" << endl; };
public:
CBase(const CBase& iOther) { cout << "CBase(const CBase& iOther) copy ctor called" << endl;
copyBase(iOther); };
virtual CBase& operator=(const CBase& iOther) { cout << "CBase& CBase::operator=(const CBase& iOther) assignment called" << endl;
if( this != &iOther ) {
copyBase(iOther); }
return *this;
};
private:
void copyBase(const CBase& iOther)
{ cout << "CBase::copyBase() copy called" << endl;
_data = iOther._data; _isvalid = iOther._isvalid; };
public: int getData() const { return _data; };
void setData(const int data) { _data = data; };
bool isValid() const { return _isvalid; };
void setValid(const bool isvalid) { _isvalid = isvalid; };
private:
int _data; bool _isvalid; };
class CDerivedA : public CBase {
private:
CDerivedA() : CBase((int) -1)
{ cout << "CDerivedA() default ctor called" << endl;
_dataA = -1.0; setValid(false); };
public:
explicit CDerivedA(const double dataA) : CBase((int) 0) { cout << "CDerivedA(const double dataA) explicit ctor called" << endl;
_dataA = dataA; };
virtual ~CDerivedA() { cout << "~CDerivedA() dtor called" << endl; };
public:
CDerivedA(const CDerivedA& iOther) : CBase(iOther) { cout << "CDerivedA(const CDerivedA& iOther) copy ctor called" << endl;
_dataA = iOther._dataA; };
virtual CDerivedA& operator=(const CDerivedA& iOther) { cout << "CDerivedA& CDerivedA::operator=(const CDerivedA& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::operator=(iOther);
_dataA = iOther._dataA; }
return *this;
};
CDerivedA(const CBase& iOther)
: CBase(iOther) { cout << "CDerivedA(const CBase& iOther) copy ctor called" << endl;
buildVirtualCopy(iOther);
};
virtual CBase& operator=(const CBase& iOther) { cout << "CBase& CDerivedA::operator=(const CBase& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::operator=(iOther);
buildVirtualCopy(iOther);
}
return *this;
};
private:
void buildVirtualCopy(const CBase& iOther)
{
cout << "CDerivedA::buildVirtualCopy copy ctor called" << endl;
const CDerivedA* pOther = dynamic_cast<const CDerivedA*> (&iOther);
if ( nullptr != pOther ) {
_dataA = pOther->_dataA;
}
else {
cout << "CDerivedA: explicit conversion from other type is forbidden" << endl;
setValid(false); }
};
public: double getDataA() const { return _dataA; };
void setDataA(const double dataA) { _dataA = dataA; };
private:
double _dataA; };
class CDerivedB : public CBase {
private:
CDerivedB() : CBase((int) -1)
{ cout << "CDerivedB() default ctor called" << endl;
_dataB = ""; setValid(false); };
public:
explicit CDerivedB(const string dataB) : CBase((int) 1) { cout << "CDerivedB(const string dataB) explicit ctor called" << endl;
_dataB = dataB; };
virtual ~CDerivedB() { cout << "~CDerivedB() dtor called" << endl; };
public:
CDerivedB(const CDerivedB& iOther) : CBase(iOther) { cout << "CDerivedB(const CDerivedB& iOther) copy ctor called" << endl;
_dataB = iOther._dataB; };
virtual CDerivedB& operator=(const CDerivedB& iOther) { cout << "CDerivedB& CDerivedB::operator=(const CDerivedB& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::operator=(iOther);
_dataB = iOther._dataB; }
return *this;
};
CDerivedB(const CBase& iOther)
: CBase(iOther) { cout << "CDerivedB(const CBase& iOther) copy ctor called" << endl;
buildVirtualCopy(iOther);
};
virtual CBase& operator=(const CBase& iOther) { cout << "CBase& CDerivedB::operator=(const CBase& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::operator=(iOther);
buildVirtualCopy(iOther);
}
return *this;
};
private:
void buildVirtualCopy(const CBase& iOther)
{
cout << "CDerivedB::buildVirtualCopy copy ctor called" << endl;
const CDerivedB* pOther = dynamic_cast<const CDerivedB*> (&iOther);
if ( nullptr != pOther ) {
_dataB = pOther->_dataB;
}
else {
const CDerivedA* pOtherA = dynamic_cast<const CDerivedA*> (&iOther);
if ( nullptr != pOtherA ) {
stringstream ss;
ss << setw(4) << pOtherA->getDataA();
_dataB = ss.str();
cout << "CDerivedB: explicit conversion from CDerivedA type" << endl;
}
else {
setValid(false); }
}
};
public: string getDataB() const { return _dataB; };
void setDataB(const string& dataB) { _dataB = dataB; };
private:
string _dataB; };
------- Polymorphism A - hierarchy --------------------
------- Polymorphism B - hierarchy --------------------
#include "stdafx.h"
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
using namespace std;
class CBase {
private:
CBase() { cout << "CBase() default ctor called" << endl;
_data = -1; _isvalid = false; };
public:
explicit CBase(const int data) { cout << "CBase(const int data) explicit ctor called" << endl;
_data = data; _isvalid = true; };
virtual ~CBase() { cout << "~CBase() dtor called" << endl; };
public:
CBase(const CBase& iOther) { cout << "CBase(const CBase& iOther) copy ctor called" << endl;
copyBase(iOther); };
CBase& operator=(const CBase& iOther) { cout << "CBase& CBase::operator=(const CBase& iOther) assignment called" << endl;
if( this != &iOther ) {
copyBase(iOther); buildVirtualCopy(iOther); }
return *this;
};
private:
void copyBase(const CBase& iOther)
{ cout << "CBase::copyBase() copy called" << endl;
_data = iOther._data; _isvalid = iOther._isvalid; };
protected:
virtual void buildVirtualCopy(const CBase& iOther) { cout << "CBase::buildVirtualCopy copy ctor called, it does nothing" << endl; };
public: int getData() const { return _data; };
void setData(const int data) { _data = data; };
bool isValid() const { return _isvalid; };
void setValid(const bool isvalid) { _isvalid = isvalid; };
private:
int _data; bool _isvalid; };
class CDerivedA : public CBase {
private:
CDerivedA() : CBase((int) -1)
{ cout << "CDerivedA() default ctor called" << endl;
_dataA = -1.0; setValid(false); };
public:
explicit CDerivedA(const double dataA) : CBase((int) 0) { cout << "CDerivedA(const double dataA) explicit ctor called" << endl;
_dataA = dataA; };
virtual ~CDerivedA() { cout << "~CDerivedA() dtor called" << endl; };
public:
CDerivedA(const CDerivedA& iOther) : CBase(iOther) { cout << "CDerivedA(const CDerivedA& iOther) copy ctor called" << endl;
_dataA = iOther._dataA; };
CDerivedA& operator=(const CDerivedA& iOther)
{ cout << "CDerivedA& CDerivedA::operator=(const CDerivedA& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::CBase(iOther); _dataA = iOther._dataA; }
return *this;
};
CDerivedA(const CBase& iOther)
: CBase(iOther) { cout << "CDerivedA(const CBase& iOther) copy ctor called" << endl;
buildVirtualCopy(iOther);
};
protected:
virtual void buildVirtualCopy(const CBase& iOther)
{
cout << "CDerivedA::buildVirtualCopy copy ctor called" << endl;
const CDerivedA* pOther = dynamic_cast<const CDerivedA*> (&iOther);
if ( nullptr != pOther ) {
_dataA = pOther->_dataA;
}
else {
cout << "CDerivedA: explicit conversion from other type is forbidden" << endl;
setValid(false); }
};
public: double getDataA() const { return _dataA; };
void setDataA(const double dataA) { _dataA = dataA; };
private:
double _dataA; };
class CDerivedB : public CBase {
private:
CDerivedB() : CBase((int) -1)
{ cout << "CDerivedB() default ctor called" << endl;
_dataB = ""; setValid(false); };
public:
explicit CDerivedB(const string dataB) : CBase((int) 1) { cout << "CDerivedB(const string dataB) explicit ctor called" << endl;
_dataB = dataB; };
virtual ~CDerivedB() { cout << "~CDerivedB() dtor called" << endl; };
public:
CDerivedB(const CDerivedB& iOther) : CBase(iOther) { cout << "CDerivedB(const CDerivedB& iOther) copy ctor called" << endl;
_dataB = iOther._dataB; };
CDerivedB& operator=(const CDerivedB& iOther)
{ cout << "CDerivedB& CDerivedB::operator=(const CDerivedB& iOther) assignment called" << endl;
if( this != &iOther ) {
this->CBase::CBase(iOther); _dataB = iOther._dataB; }
return *this;
};
CDerivedB(const CBase& iOther) : CBase(iOther) { cout << "CDerivedB(const CBase& iOther) copy ctor called" << endl;
buildVirtualCopy(iOther);
};
protected:
virtual void buildVirtualCopy(const CBase& iOther)
{
cout << "CDerivedB::buildVirtualCopy copy ctor called" << endl;
const CDerivedB* pOther = dynamic_cast<const CDerivedB*> (&iOther);
if ( nullptr != pOther ) {
_dataB = pOther->_dataB;
}
else {
const CDerivedA* pOtherA = dynamic_cast<const CDerivedA*> (&iOther);
if ( nullptr != pOtherA ) {
stringstream ss;
ss << setw(4) << pOtherA->getDataA();
_dataB = ss.str();
cout << "CDerivedB: explicit conversion from CDerivedA type" << endl;
}
else {
setValid(false); }
}
};
public: string getDataB() const { return _dataB; };
void setDataB(const string& dataB) { _dataB = dataB; };
private:
string _dataB; };
------- Polymorphism B - hierarchy --------------------
and a simple test program to test both of them:
------- test program for both hierarchies -------------
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Program starts..." << endl;
cout << endl;
{
CDerivedA* pA0 = new CDerivedA((double) 1.0);
CDerivedA* pA1 = new CDerivedA((double) 2.0);
CDerivedB* pB0 = new CDerivedB(string("This is B1"));
CDerivedB* pB1 = new CDerivedB(string("This is B2"));
cout << endl;
CBase* p00 = nullptr;
CBase* p01 = nullptr;
cout << "Assignment via base pointers of type A objects" << endl;
p00 = pA0;
p01 = pA1;
*p00 = *p01;
cout << "pA0 dataA = " << pA0->getDataA() << endl;
cout << "pA1 dataA = " << pA1->getDataA() << endl;
cout << endl;
p00 = nullptr;
p01 = nullptr;
cout << "Assignment via base pointers of type B objects" << endl;
p00 = pB0;
p01 = pB1;
*p00 = *p01;
cout << "pB0 dataB = " << pB0->getDataB() << endl;
cout << "pB1 dataB = " << pB1->getDataB() << endl;
cout << endl;
p00 = nullptr;
p01 = nullptr;
cout << "Cross Assignment via base pointers from type B objects to type A is forbidden" << endl;
p00 = pA0;
p01 = pB0;
cout << "p00 is pointing to pA0 " << endl;
*p00 = *p01;
cout << "p00 is valid = " << p00->isValid() << endl;
cout << endl;
p00 = nullptr;
p01 = nullptr;
cout << "Cross Assignment via base pointers from type A objects to type B" << endl;
cout << "is allowed by custom conversion... " << endl;
p00 = pB1;
p01 = pA1;
cout << "p00 is pointing to pB1 " << endl;
*p00 = *p01;
cout << "p00 is valid = " << p00->isValid() << endl;
cout << "p00 --> pB1 dataB = " << pB1->getDataB() << endl;
cout << endl;
p00 = nullptr;
p01 = nullptr;
delete pA0;
delete pA1;
delete pB0;
delete pB1;
cout << endl;
}
{
CDerivedA* pA0 = new CDerivedA((double) 1.0);
CDerivedA* pA1 = new CDerivedA((double) 2.0);
CDerivedB* pB0 = new CDerivedB(string("This is B1"));
CDerivedB* pB1 = new CDerivedB(string("This is B2"));
cout << endl;
cout << "Assignment via pointers of type A objects" << endl;
*pA0 = *pA1;
cout << "pA0 dataA = " << pA0->getDataA() << endl;
cout << "pA1 dataA = " << pA1->getDataA() << endl;
cout << endl;
cout << "Assignment via pointers of type B objects" << endl;
*pB0 = *pB1;
cout << "pB0 dataB = " << pB0->getDataB() << endl;
cout << "pB1 dataB = " << pB1->getDataB() << endl;
cout << endl;
delete pA0;
delete pA1;
delete pB0;
delete pB1;
cout << endl;
}
{
cout << "Base class Assignment just works." << endl;
CBase* p00 = nullptr;
CBase* p01 = nullptr;
p00 = new CBase((int) 10);
p01 = new CBase((int) 11);
*p00 = *p01;
cout << "p00 is valid = " << p00->isValid() << endl;
cout << "p00 data = " << p00->getData() << endl;
cout << "p01 is valid = " << p01->isValid() << endl;
cout << "p01 data = " << p01->getData() << endl;
cout << endl;
delete p00;
cout << endl;
cout << "Base class copy ctor just works." << endl;
p00 = new CBase(*p01);
cout << "p00 is valid = " << p00->isValid() << endl;
cout << "p00 data = " << p00->getData() << endl;
delete p00;
delete p01;
cout << endl;
}
{
cout << "Copy ctor via pointers of type A objects" << endl;
CDerivedA* pA1 = new CDerivedA((double) 2.0);
cout << endl;
CDerivedA* pA2 = new CDerivedA(*pA1);
cout << "pA1 dataA = " << pA1->getDataA() << endl;
cout << "pA2 dataA = " << pA2->getDataA() << endl;
delete pA1;
delete pA2;
cout << endl;
cout << "Copy ctor via pointers of type B objects" << endl;
CDerivedB* pB1 = new CDerivedB(string("This is B2"));
cout << endl;
CDerivedB* pB2 = new CDerivedB(*pB1);
cout << "pB1 dataB = " << pB1->getDataB() << endl;
cout << "pB2 dataB = " << pB2->getDataB() << endl;
delete pB1;
delete pB2;
cout << endl;
cout << "Copy ctor via base pointers of type A,B objects" << endl;
CBase* p00 = new CDerivedA((double) 1.0);
CBase* p01 = new CDerivedB(string("This is B1"));
cout << endl;
cout << "A from A via base" << endl;
CDerivedA* pA3 = new CDerivedA(*p00);
cout << endl;
cout << "base from A (slicing)" << endl;
CBase* pA4 = new CBase(*p00); cout << endl;
cout << "B from B via base" << endl;
CDerivedB* pB3 = new CDerivedB(*p01);
cout << endl;
cout << "base from B (slicing)" << endl;
CBase* pB4 = new CBase(*p01); cout << endl;
cout << "A from B via base" << endl;
CDerivedA* pA5 = new CDerivedA(*p01);
cout << endl;
cout << "B from A via base" << endl;
CDerivedB* pB5 = new CDerivedB(*p00);
cout << endl;
delete pA3;
delete pA4;
delete pA5;
delete pB3;
delete pB4;
delete pB5;
delete p00;
delete p01;
cout << endl;
}
int k = getchar();
return 0;
}
------- test program for both hierarchies -------------
Thanks in advance for any suggestion about why you would go with one instead of the other
(or, if eventually you do know a better idiomatic solution).
Federico
|
|
|
|
|
That looks like a shed load of code just to implement copying and assignment. Are you sure that copying objects of arbitrary types is both necessary to your design and won't turn into a complete millstone around your development team's neck? They might not thank you when they have to grind that lot out again to implement a new class? I'm also wincing at how the assignment operators are written - the canonical way you write an assignment operator in C++ is to use a copy and swap.
So... What would I suggest? Firstly go back to your design and see if it can be reworked to use a set of relatively simple principles:
- value types have no polymorphic behaviour and are copy constructable and assignable if appropriate. Use copy and swap to write the assignment operator for a value type
- polymorphic types are accessed through interfaces. Don't assign or copy the objects themselves, reference them through pointers or references to the interfaces they implement. The only place that knows the concrete type of a polymorphic type is the lump of code that creates the object
- don't use implementation inheritance. Containment gives far less headaches
- minimise manual memory management wherever possible. Use parameterise from above (PFA) and objects created on the stack wherever possible. If you write a delete statement pinch yourself and look at using std::unique_ptr or std::shared_ptr instead. RAII is your friend
- make everything exception safe but don't handle exceptions in too many places. One try/catch set in a function
If there's still a need to deep copy objects through pointers to arbitrary base classes then consider implementing a clonable interface. Never slice objects - once you lop off the context you can never get it back.
|
|
|
|
|
Thanks Aescleal,
all the techniques you suggest are fine, but my point was more on the discussion
of the copy ctor and assignment op. themselves: it is clear that if I make them
private, or if I just use the compiler generated ones for POD types, there will
be no worry.
By the way what do you mean exactly by "copy and swap" ? Do you mean this ? :
Object& operator = (const Object& other)
{
Object(other).swap(*this);
return *this;
}
(How do you ensure no self assignment in this case ?, by forwarding to std::swap ?)
My point anyway was about how to do in the correct way when I've a hierarchy,
I've deep copies, I've to be able to use base class pointers or derived pointers:
i.e. in the most general case.
In this general case it seems to me that you're forced to use one of the given approaches,
and that you shall handle all cases of copy ctor and assignment ops explicitly
(derived from derived, derived from base, base from derived, base from base)
maybe just disallowing some of them.
Just to be clear, my point is the following:
CBase* pbase0 = new CDerived(...);
CBase* pbase1 = new CDerived(...);
*pbase0 = *pbase1
Bye
Federico
modified 22-Oct-13 4:44am.
|
|
|
|
|
Generally: Deep hierarchies (i.e. anything more than inheriting an interface) are bad news. Implementation inheritance is the strongest coupling there is and you'll end up with fragile logical designs (you'll spend ages trying to work out what goes where in your class taxonomy and find you have to shuffle a lot of members around) and long build times (when you shuffle you'll have to rebuild the world). If you stick to parameterise from above and interface inheritance you won't have to copy objects, just references and the whole question becomes moot.
Copy and swap is:
T &T::operator=( const T &t )
{
T temp( t );
swap( temp );
return *this;
}
where swap is non-throwing. You get exception safety for free and if you use the PIMPL idiom and lean on std::unique_ptr it's pretty trivial to implement.
|
|
|
|
|
Hello Aesclal,
thanks again, may I ask you (if you got the time) to append some links
in order to let other readers as well understand the topic ?
(e.g. spelling out what is PFA - parameterise from above - and its coupling with interface
inheritance, why you will then work only with references, etc...).
The best would be a link to a public domain example...
About "swap", I left it out first from my discussion in order to focus only on copy ctor
& assignment operators, otherwise you should add also the swap method to the examples.
Anyway, usually I would add this to the assignment op:
T &T::operator=( const T &t )
{
if ( this != &t ) {
T temp( t );
swap( temp );
}
return *this;
}
The PIMPL idiom (for the sake of other readers) is the private implementation idiom.
Bye
Federico
|
|
|
|
|
HI,
I am using SQLFetchScroll for bulk reading from DB .But it is failing for some tables loading where columns contain NULL values.
Can anyone help me on this to get rid of this?
Regards,
ASH
asdsa
|
|
|
|
|
Have you checked the return value to see how it's different from when it succeeds?
Have you seen the diagnostics information provided in the documentation page[^]?
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Yes, Rajesh I have checked the return code is -11072.. I am not able to find any related document for this error code
Any help is appreciate..
Thanks,
Ashish
asdsa
|
|
|
|
|
I'd probably try switch ing the return value to one of the values documented.
The possible return values documented are: SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA, SQL_STILL_EXECUTING, SQL_ERROR, SQL_INVALID_HANDLE.
Or you could look up the definitions of these return values to see if any of these are defined as -11072.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Showing a relevant piece of code here might make things easier too.
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
// NumRowsFetched.
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, sizeof(ORDERINFO), 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, ROW_ARRAY_SIZE, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);
SQLSetStmtAttr(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &NumRowsFetched, 0);
// Bind elements of the first structure in the array to the OrderID,
// SalesPerson, and Status columns.
SQLBindCol(hstmt, 1, SQL_C_ULONG, &OrderInfoArray[0].OrderID, 0, &OrderInfoArray[0].OrderIDInd);
SQLBindCol(hstmt, 2, SQL_C_CHAR, OrderInfoArray[0].SalesPerson,
sizeof(OrderInfoArray[0].SalesPerson),
&OrderInfoArray[0].SalesPersonLenOrInd);
SQLBindCol(hstmt, 3, SQL_C_CHAR, OrderInfoArray[0].Status,
sizeof(OrderInfoArray[0].Status), &OrderInfoArray[0].StatusLenOrInd);
// Execute a statement to retrieve rows from the Orders table.
SQLExecDirect(hstmt, "SELECT OrderID, SalesPerson, Status FROM Orders", SQL_NTS);
// Fetch up to the rowset size number of rows at a time. Print the actual
// number of rows fetched; this number is returned in NumRowsFetched.
// Check the row status array to print only those rows successfully
// fetched. Code to check if rc equals SQL_SUCCESS_WITH_INFO or
// SQL_ERRORnot shown.
while ((rc = SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0)) != SQL_NO_DATA) {
asdsa
|
|
|
|
|
So, you've pasted here some code from MSDN[^].
If you're trying that sample mentioned in MSDN, do you have a replica of that database on your DB server?
How many iterations does the loop run, and what is the value that the call returns each time? And if it's that integer value you mentioned earlier, have you tried looking up the header files to see which valid return type is defined as that number? Please try this, and tell me what you find.
And in case you just pasted some random code from MSDN here in the hope that I'll setup a database here and do all the work to figure out what things could go wrong, ... I really don't have to be doing this at 3AM, you know?
"Real men drive manual transmission" - Rajesh.
|
|
|
|
|
Hey there,
I have a function called,
App 1:
void GetImage(CImage * img)
{
//Pass &img over socket to another app
}
App 2:
void DisplayImage()
{
CImage * pImg = &img;
}
Is it possible to pass a class pointer as memory buffer across the socket?
The above code is just an example. My question in general is, whether it's possible to pass any Classes pointer as a memory buffer across sockets.
UPDATE:
This is within same process. In that case can i simply pass the pointer over socket?
Another catch here is, i need to encode all the data in a XML format before sending across the socket.
C++ Code:
CImage *pImage; //pImage hold the data
Inside XML:
<param />&pImage
Can i do like this?
Thanks
modified 15-Oct-13 12:48pm.
|
|
|
|
|
Don Guy wrote: My question in general is, whether it's possible to pass any Classes pointer as
a memory buffer across sockets
That depends. Are you passing it between different processes? If so, then the pointer will have no meaning in the context of the receiving process.
Remember that each process has its own allocation of memory that is separate from every other process. Therefore a memory pointer has no meaning outside its own process.
However, you could send the object itself through a process of serialization: http://msdn.microsoft.com/en-us/library/6bz744w8.aspx[^]
The difficult we do right away...
...the impossible takes slightly longer.
modified 14-Oct-13 20:49pm.
|
|
|
|
|