473,553 Members | 3,116 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Virtual function and inheritance question

Hello,

My question involves virtual functions and inheritance.

Suppose we have a class structure, that consists of "data" classes, and
"processor" classes. The data classes are derived from BufferBase, and
customized in order to be able to a type of data (of any kind, such as
chunks of audio samples from a sound card). The processor classes are
derived from ProcessorBase, and are customized to handle
BufferBase-derived objects. Each BufferBase-derived class has a
corresponding ProcessorBase-derived class.

The following code summarizes this:

//=============== ==
// Base classes

class BufferBase
{
public:
// Some arbitrary method for putting data into the buffer.
virtual void StoreData(void *data, int size);
};

class ProcessorBase
{
public:
// Virtual method, which derived classes implement to
// handle incoming data.
virtual void HandleBuffer(Bu fferBase &buffer) = 0;
};

//=============== ==
// Derived classes

class BufferDerived : public BufferBase
{
// custom functions and data
};

// Class to handle BufferDerived objects
class ProcessorDerive d : public ProcessorBase
{
public:
// Implement the pure virtual method in the base class
virtual void HandleBuffer(Bu fferBase &buffer)
{
// process data buffer
}

// Override the virtual method
virtual void HandleBuffer(Bu fferDerived &buffer)
{
// process data buffer
}
};
My question then is, if the following code is executed:

BufferBase buffer1;
BufferDerived buffer2;

// We will access the ProcessorDerive d object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerive d;

processor->HandleBuffer(b uffer1); // Case #1
processor->HandleBuffer(b uffer2); // Case #2

In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?

(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)

Regards,
Markus.

Dec 29 '06 #1
7 2103

Markus Svilans wrote:
Hello,

My question involves virtual functions and inheritance.

Suppose we have a class structure, that consists of "data" classes, and
"processor" classes. The data classes are derived from BufferBase, and
customized in order to be able to a type of data (of any kind, such as
chunks of audio samples from a sound card). The processor classes are
derived from ProcessorBase, and are customized to handle
BufferBase-derived objects. Each BufferBase-derived class has a
corresponding ProcessorBase-derived class.

The following code summarizes this:

//=============== ==
// Base classes

class BufferBase
{
public:
// Some arbitrary method for putting data into the buffer.
virtual void StoreData(void *data, int size);
};
Instead of void* data, why don't you template the class. You'll freak
out over the enormous amount of code you'll save and that buffer could
then be used to store anything. Anything including your own user-types.
Add to that the fact that the compiler's type checking ability is not
disabled. Programming with void* data is like walking around
blind-folded.
(see template below).
>
class ProcessorBase
{
public:
// Virtual method, which derived classes implement to
// handle incoming data.
virtual void HandleBuffer(Bu fferBase &buffer) = 0;
};

//=============== ==
// Derived classes

class BufferDerived : public BufferBase
{
// custom functions and data
};

// Class to handle BufferDerived objects
class ProcessorDerive d : public ProcessorBase
{
public:
// Implement the pure virtual method in the base class
virtual void HandleBuffer(Bu fferBase &buffer)
{
// process data buffer
}

// Override the virtual method
virtual void HandleBuffer(Bu fferDerived &buffer)
{
// process data buffer
}
};
My question then is, if the following code is executed:

BufferBase buffer1;
BufferDerived buffer2;

// We will access the ProcessorDerive d object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerive d;

processor->HandleBuffer(b uffer1); // Case #1
processor->HandleBuffer(b uffer2); // Case #2

In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?

(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)
The second virtual member function
void ProcessorDerive d::HandleBuffer (BufferDerived &buffer) { ... }
is not needed

You need to make ProcessorBase's destructor virtual.
Modify the
void ProcessorDerive d::HandleBuffer (BufferBase &buffer)
as follows:

....
#include <typeinfo>

class ProcessorDerive d : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(Bu fferBase &buffer)
{
std::cout << "ProcessorDeriv ed::HandleBuffe r(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer). name();
std::cout << std::endl;
}
};

and you'll get something like:
ProcessorDerive d::HandleBuffer (BufferBase &buffer)
buffer's type is BufferBase
ProcessorDerive d::HandleBuffer (BufferBase &buffer)
buffer's type is BufferDerived // <- note !!!

You don't need the second function taking a BufferDerived parameter.

___
Now, for the template:

#include <iostream>
#include <ostream>
#include <vector>

template< typename T >
class BufferBase
{
std::vector< T vt;
public:
BufferBase(size _t sz = 0, const T& t = T())
: vt(sz, t) { }
BufferBase(cons t BufferBase& copy)
{
vt = copy.vt;
}
/* member functions */
size_t size() const { return vt.size(); }
/* friend op<< */
friend std::ostream&
operator<<(std: :ostream& os, const BufferBase& r_bb)
{
typedef typename std::vector< T >::const_iterat or VIter;
for(VIter viter = r_bb.vt.begin() ;
viter != r_bb.vt.end();
++viter)
{
os << *viter << " ";
}
return os;
}
};

int main()
{

BufferBase< int buffer(10);
std::cout << "buffer size = " << buffer.size() << std::endl;
std::cout << buffer << std::endl;

BufferBase< char cbuffer(10, 'a');
std::cout << "buffer size = " << cbuffer.size() << std::endl;
for(char c = 'b'; c < 'z'; ++c)
{
cbuffer.push_ba ck(c);
}
std::cout << "buffer size = " << cbuffer.size() << std::endl;
std::cout << cbuffer << std::endl;

return 0;
}

/*
buffer size = 10
0 0 0 0 0 0 0 0 0 0
buffer size = 10
buffer size = 34
a a a a a a a a a a b c d e f g h i j k l m n o p q r s t u v w x y
*/

Dec 29 '06 #2
ProcessorDerive d class's function shall get invoked since the function
is declared as virtual in which case the message is passed based on the
type of class it is refering to rather than the type of the object
itself.

Salt_Peter wrote:
My question then is, if the following code is executed:

BufferBase buffer1;
BufferDerived buffer2;

// We will access the ProcessorDerive d object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerive d;

processor->HandleBuffer(b uffer1); // Case #1
processor->HandleBuffer(b uffer2); // Case #2

In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?

(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)
Dec 29 '06 #3

Sandip Shahane wrote:
ProcessorDerive d class's function shall get invoked since the function
is declared as virtual in which case the message is passed based on the
type of class it is refering to rather than the type of the object
itself.
Don't top Post, please.
The fact that it is ProcessorDerive d's function that gets called is
something the OP is already aware of.
The point was that the parameter reference is taken polymorphicly.
And the second function doesn't match the virtual function's signature
anyways.
>
Salt_Peter wrote:
My question then is, if the following code is executed:
>
BufferBase buffer1;
BufferDerived buffer2;
>
// We will access the ProcessorDerive d object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerive d;
>
processor->HandleBuffer(b uffer1); // Case #1
processor->HandleBuffer(b uffer2); // Case #2
>
In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?
>
(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)
Dec 30 '06 #4
Salt_Peter wrote:
Markus Svilans wrote:
[ snip ]

Instead of void* data, why don't you template the class. You'll freak
out over the enormous amount of code you'll save and that buffer could
then be used to store anything. Anything including your own user-types.
Add to that the fact that the compiler's type checking ability is not
disabled. Programming with void* data is like walking around
blind-folded.
(see template below).
Good analogy! Thanks for the suggestion to use a template for the data
buffers. It's a very good idea. A fine example of great advice on
comp.lang.c++.

In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?

(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)

The second virtual member function
void ProcessorDerive d::HandleBuffer (BufferDerived &buffer) { ... }
is not needed

You need to make ProcessorBase's destructor virtual.
Another good tip. I do this in my real code, but for the example code I
chose not to show any destructors.
Modify the
void ProcessorDerive d::HandleBuffer (BufferBase &buffer)
as follows:

...
#include <typeinfo>

class ProcessorDerive d : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(Bu fferBase &buffer)
{
std::cout << "ProcessorDeriv ed::HandleBuffe r(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer). name();
std::cout << std::endl;
}
};

I gather then that using RTTI is the only way to go here.

Are there any good articles available online that outline the
performance penalties (if any) incurred when using RTTI?

The HandleBuffer() method may end up being called very frequently
(100's or 1000's of times per second) so I would like to make the
dispatching as fast as possible.
___
Now, for the template:

#include <iostream>
#include <ostream>
#include <vector>

template< typename T >
class BufferBase
{
Thanks for sharing the template code.

At the beginning, when I started working on this code, I opted not to
use a std::vector based implementation. Instead I chose to use my own
managed array class, because I needed access to contiguous elements in
memory (mainly for interoperabilit y with C API functions).

Another article on this newsgroup brought my attention to this FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-34.3

Because std::vector does allow seamless integration with C functions,
which require a pointer to a contiguous array of objects, I'm now going
to switch to an std::vector based implementation.

Regards,
Markus.

Dec 30 '06 #5

Markus Svilans wrote:
Salt_Peter wrote:
Markus Svilans wrote:
[ snip ]
Instead of void* data, why don't you template the class. You'll freak
out over the enormous amount of code you'll save and that buffer could
then be used to store anything. Anything including your own user-types.
Add to that the fact that the compiler's type checking ability is not
disabled. Programming with void* data is like walking around
blind-folded.
(see template below).

Good analogy! Thanks for the suggestion to use a template for the data
buffers. It's a very good idea. A fine example of great advice on
comp.lang.c++.

In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerive d object gets called?
>
(My reasoning says that in both cases, HandleBuffer(Bu fferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)
The second virtual member function
void ProcessorDerive d::HandleBuffer (BufferDerived &buffer) { ... }
is not needed

You need to make ProcessorBase's destructor virtual.

Another good tip. I do this in my real code, but for the example code I
chose not to show any destructors.
Modify the
void ProcessorDerive d::HandleBuffer (BufferBase &buffer)
as follows:

...
#include <typeinfo>

class ProcessorDerive d : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(Bu fferBase &buffer)
{
std::cout << "ProcessorDeriv ed::HandleBuffe r(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer). name();
std::cout << std::endl;
}
};


I gather then that using RTTI is the only way to go here.
no, i just used typeid to show you that the reference is actually
pointing to a derived object with no need to cast anything. References,
not just pointers, work nicely with polymorphic objects.
In the event that you have some virtual member function in BufferBase
and its derivatives, these will get called polymorphicly and
transparently in void HandleBuffer(Bu fferBase &buffer).
>
Are there any good articles available online that outline the
performance penalties (if any) incurred when using RTTI?
There is no real need to use RTTI here. Polymorphism is what you need.
>
The HandleBuffer() method may end up being called very frequently
(100's or 1000's of times per second) so I would like to make the
dispatching as fast as possible.
Contrary to popular opinion, in the situation you've described, there
is a cost in not using polymorphism. Specially when the cost includes
having to write the code. The cost of virtual calls themselves is
often, not always, a performance enhancement. You'ld have to compare.
>

___
Now, for the template:

#include <iostream>
#include <ostream>
#include <vector>

template< typename T >
class BufferBase
{

Thanks for sharing the template code.

At the beginning, when I started working on this code, I opted not to
use a std::vector based implementation. Instead I chose to use my own
managed array class, because I needed access to contiguous elements in
memory (mainly for interoperabilit y with C API functions).

Another article on this newsgroup brought my attention to this FAQ:
http://www.parashift.com/c++-faq-lit....html#faq-34.3

Because std::vector does allow seamless integration with C functions,
which require a pointer to a contiguous array of objects, I'm now going
to switch to an std::vector based implementation.
You've done well to research it. A std::vector is a very capable
container. Its dynamic, copyable, fast and opens the door to a slew of
algorithms you can throw at it. Its only weakness is dynamic
reallocation which is easily fixed with an appropriate resize().
Building your *own* container class with a std::vector member is easy,
safe and simple. Including with iterator support. As you go along,
you'll find yourself designing your container classes using
std::vector's own inteface, its quite well designed.

With many std::vector implementations , you'll find they are actually
faster than a primitive array by about 5% to 10% and more if the
dataset is sizeable. You won't see the speed benefit until you compile
in release mode (not debug).
What is nice is being able to use const references, references, stream
its elements or overload operators, etc. It also has a range_checking
member function at(...). The list goes on and on.
example with the proverbial templated op<<...

#include <iostream>
#include <ostream>
#include <vector>

template< typename T >
std::ostream&
operator<<(std: :ostream& os, std::vector< T >& vt)
{
typedef typename std::vector< T >::iterator VIter;
for( VIter viter = vt.begin(); viter != vt.end(); ++viter )
{
os << *viter;
if(viter != --vt.end()) os << ", ";
}
return os;
}

int main()
{
std::vector< double vd(10, 11.1);
std::cout << vd << std::endl;

std::vector< char vc(10, 'a');
vc.push_back('b ');
std::cout << vc << std::endl;

std/::vector< char vc2( vc ); // 11 chars copied
}

/*
11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1, 11.1
a, a, a, a, a, a, a, a, a, a, b
*/

Dec 31 '06 #6

Salt_Peter wrote:
class ProcessorDerive d : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(Bu fferBase &buffer)
{
std::cout << "ProcessorDeriv ed::HandleBuffe r(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer). name();
std::cout << std::endl;
}
};

I gather then that using RTTI is the only way to go here.

no, i just used typeid to show you that the reference is actually
pointing to a derived object with no need to cast anything. References,
not just pointers, work nicely with polymorphic objects.
In the event that you have some virtual member function in BufferBase
and its derivatives, these will get called polymorphicly and
transparently in void HandleBuffer(Bu fferBase &buffer).
I see that.

However, in my original question I was wondering what happens if you
call a virtual method in the base class, that has been overridden in a
derived class. In the example code I showed, ProcessorDerive d had two
methods:

HandleBuffer(Bu fferBase &buffer) // inherited from ProcessorBase
HandleBuffer(Bu fferDerived &buffer) // a new, overridden version in
ProcessorDerive d

After some experimenting, it became clear that the inherited version is
always the one that is invoked, when calling through a base class
pointer (in this case through a ProcessorBase pointer). The overridden
version is only called when calling from a derived class pointer.
Are there any good articles available online that outline the
performance penalties (if any) incurred when using RTTI?

There is no real need to use RTTI here. Polymorphism is what you need.
This is true.

However given the class hierarchy described in my original message,
what I'm looking for is some safe way of passing BufferBase-derived
objects to the correct ProcessorBase-derived objects.

Imagine we had the following additional classes:

// Imaginary class that stores a chunk of audio from an audio stream
class AudioBuffer : public BufferBase
{
private:
int timestamp;
// ... other data members and methods ...
public:
// ... public methods, constructors and destructors
};

// Imaginary class that stores a frame from a video data stream
class VideoFrameBuffe r : public BufferBase
{
private:
// The video frame stores in some Bitmap object
Bitmap frame;
public:
// ... public methods, constructors and destructors
};

class AudioProcessor : public ProcessorBase
{
public:
// Inherited from ProcessorBase
virtual void HandleBuffer(Bu fferBase &buffer);
};

What I'm really after is a fast and safe way of automatically ensuring
that the AudioProcessor: :HandleBuffer() method can only be passed
AudioBuffer objects, and not VideoFrameBuffe r objects, or other objects
derived from BufferBase.

For example, if somehow an VideoFrameBuffe r object gets passed to an
AudioProcessor, it would be nice if an exception were automatically
thrown.

Currently, the only method that comes to my mind is to use
dynamic_cast, or other form of RTTI, in AudioProcessor: :HandleBuffer to
ensure that the passed buffer is an AudioBuffer.

Any ideas for how do to this?

(I thought of using a templated virtual method in the base class, but
apparently you can't create virtual methods that are also templates.)

The HandleBuffer() method may end up being called very frequently
(100's or 1000's of times per second) so I would like to make the
dispatching as fast as possible.

Contrary to popular opinion, in the situation you've described, there
is a cost in not using polymorphism. Specially when the cost includes
having to write the code. The cost of virtual calls themselves is
often, not always, a performance enhancement. You'ld have to compare.
I'm definitely a fan of polymorphism. I'm not trying to start any fires
when I say that in my opinion this is one of the great advantages of
C++ (and other OO languages) over C and other non-OO languages.

Regards,
Markus.

Dec 31 '06 #7

Markus Svilans wrote:
Salt_Peter wrote:
class ProcessorDerive d : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(Bu fferBase &buffer)
{
std::cout << "ProcessorDeriv ed::HandleBuffe r(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer). name();
std::cout << std::endl;
}
};
>
>
I gather then that using RTTI is the only way to go here.
no, i just used typeid to show you that the reference is actually
pointing to a derived object with no need to cast anything. References,
not just pointers, work nicely with polymorphic objects.
In the event that you have some virtual member function in BufferBase
and its derivatives, these will get called polymorphicly and
transparently in void HandleBuffer(Bu fferBase &buffer).

I see that.

However, in my original question I was wondering what happens if you
call a virtual method in the base class, that has been overridden in a
derived class. In the example code I showed, ProcessorDerive d had two
methods:

HandleBuffer(Bu fferBase &buffer) // inherited from ProcessorBase
HandleBuffer(Bu fferDerived &buffer) // a new, overridden version in
ProcessorDerive d

After some experimenting, it became clear that the inherited version is
always the one that is invoked, when calling through a base class
pointer (in this case through a ProcessorBase pointer). The overridden
version is only called when calling from a derived class pointer.
Are there any good articles available online that outline the
performance penalties (if any) incurred when using RTTI?
There is no real need to use RTTI here. Polymorphism is what you need.

This is true.

However given the class hierarchy described in my original message,
what I'm looking for is some safe way of passing BufferBase-derived
objects to the correct ProcessorBase-derived objects.

Imagine we had the following additional classes:

// Imaginary class that stores a chunk of audio from an audio stream
class AudioBuffer : public BufferBase
{
private:
int timestamp;
// ... other data members and methods ...
public:
// ... public methods, constructors and destructors
};

// Imaginary class that stores a frame from a video data stream
class VideoFrameBuffe r : public BufferBase
{
private:
// The video frame stores in some Bitmap object
Bitmap frame;
public:
// ... public methods, constructors and destructors
};

class AudioProcessor : public ProcessorBase
{
public:
// Inherited from ProcessorBase
virtual void HandleBuffer(Bu fferBase &buffer);
};

What I'm really after is a fast and safe way of automatically ensuring
that the AudioProcessor: :HandleBuffer() method can only be passed
AudioBuffer objects, and not VideoFrameBuffe r objects, or other objects
derived from BufferBase.
No problem, use templates.
The compiler has no choice but to create those versions of the
templates you use. It can't call the wrong buffer with a processor
because no virtual member function would exist to match the call.
No RTTI needed unless you plan to make soup.
Of course, that means you'll need to store Audio things seperate from
Video things (ie: seperate containers). Note that default template
parameters below means that < must still be used to declare the
derived processors in main().

#include <iostream>
#include <ostream>
#include <vector>

class BufferBase {
public:
BufferBase() { }
virtual ~BufferBase() { }
};

class AudioBuffer : public BufferBase { };

class VideoBuffer : public BufferBase { };

template< typename BufferType >
class ProcessorBase {
public:
virtual ~ProcessorBase( ) { }
virtual void HandleBuffer(Bu fferType &buffer) = 0;
};

template< typename BufferType = AudioBuffer >
class AudioProcessor : public ProcessorBase< BufferType {
public:
virtual void HandleBuffer(Bu fferType &buffer) {
std::cout << "AudioProcessor ::HandleBuffer( ...)\n";
}
};

template< typename BufferType = VideoBuffer >
class VideoProcessor : public ProcessorBase< BufferType {
public:
virtual void HandleBuffer(Bu fferType &buffer) {
std::cout << "VideoProcessor ::HandleBuffer( ...)\n";
}
};

int main() {
VideoBuffer vidbuf;
VideoProcessor< vidproc;
vidproc.HandleB uffer( vidbuf );

AudioBuffer audiobuf;
AudioProcessor< audioproc;
audioproc.Handl eBuffer( audiobuf );

// test
// audioproc.Handl eBuffer( vidbuf ); // error: no matching call
}

If you uncomment the error, the compiler doesn't even let you compile
the program.

Dec 31 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
2989
by: Michael Winter | last post by:
Until about 5 minutes ago, I was happy with my knowledge of virtual functions - then I read "Mixing interface and functional inheritance" posted by Kevin L. earlier today. All of a sudden, I found out that you can inherit using the virtual keyword: class A { } class B : public *virtual* A
4
4638
by: Sat | last post by:
Hi, I have a simplified version of a problem that I am facing (hope I haven't oversimplified it). This code doesn't work now and I want to find how I can make it work. Can I call the derived class version from the base class pointer and still be able to use a vector with derived element pointers? class BaseElem { }; class DerivedElem1...
4
2887
by: JKop | last post by:
I'm starting to think that whenever you derive one class from another, that you should use virtual inheritance *all* the time, unless you have an explicit reason not to. I'm even thinking that there shouldn't have been a "virtual" keyword for this purpose, but instead, a "nonvirtual" keyword! In teaching inheritance, you see the common...
14
1903
by: Bruno van Dooren | last post by:
Hi all, i am having a problems with inheritance. consider the following: class A { public: A(int i){;} };
20
1991
by: Daniel | last post by:
I have the following three classes class A { public: virtual void f() = 0; }; class B: public A {
3
1704
by: Imre | last post by:
Hi! I've got some questions regarding heavy use of virtual inheritance. First, let's see a theoretical situation, where I might feel tempted to use a lot of virtual inheritance. Let's suppose, we're creating a little strategy game. In our game, there are Units. A Unit can be either a Human, or a Vehicle. Obviously, Human and Vehicle...
2
1836
by: Heinz Ketchup | last post by:
Hello, I'm looking to bounce ideas off of anyone, since mainly the idea of using Multiple Virtual Inheritance seems rather nutty. I chalk it up to my lack of C++ Experience. Here is my scenario... I have 5 Derived Classes I have 3 Base Classes
12
2642
by: mijobee | last post by:
I'm very new to c++ and just writing some code to learn. I've run into a problem, with a javaish design, and want to know if there is any possible solution without modifying the design. I've read up on virtual inheritance and from my understanding this should work fine but I haven't found any docs that use such a tangled example. The gcc...
5
1972
by: toton | last post by:
Hi, I want a few of my class to overload from a base class, where the base class contains common functionality. This is to avoid repetition of code, and may be reducing amount of code in binary, not to get polymorphic behavior. None of them has virtual methods, and are self contained (no destructor at all) thus do not have a chance to have...
0
7568
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7492
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7772
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8007
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7526
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6109
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5409
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5133
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3537
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.