473,386 Members | 1,793 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

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(BufferBase &buffer) = 0;
};

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

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

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

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

BufferBase buffer1;
BufferDerived buffer2;

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

processor->HandleBuffer(buffer1); // Case #1
processor->HandleBuffer(buffer2); // Case #2

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

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

Regards,
Markus.

Dec 29 '06 #1
7 2086

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(BufferBase &buffer) = 0;
};

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

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

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

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

BufferBase buffer1;
BufferDerived buffer2;

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

processor->HandleBuffer(buffer1); // Case #1
processor->HandleBuffer(buffer2); // Case #2

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

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

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

....
#include <typeinfo>

class ProcessorDerived : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(BufferBase &buffer)
{
std::cout << "ProcessorDerived::HandleBuffer(BufferBase
&buffer)\n";
std::cout << "buffer's type is " << typeid(buffer).name();
std::cout << std::endl;
}
};

and you'll get something like:
ProcessorDerived::HandleBuffer(BufferBase &buffer)
buffer's type is BufferBase
ProcessorDerived::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(const 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_iterator 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_back(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
ProcessorDerived 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 ProcessorDerived object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerived;

processor->HandleBuffer(buffer1); // Case #1
processor->HandleBuffer(buffer2); // Case #2

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

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

Sandip Shahane wrote:
ProcessorDerived 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 ProcessorDerived'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 ProcessorDerived object through a
// base class pointer.
ProcessorBase *processor = new ProcessorDerived;
>
processor->HandleBuffer(buffer1); // Case #1
processor->HandleBuffer(buffer2); // Case #2
>
In each of the cases, #1 and #2, which version of the HandleBuffer()
method in the ProcessorDerived object gets called?
>
(My reasoning says that in both cases, HandleBuffer(BufferBase &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 ProcessorDerived object gets called?

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

The second virtual member function
void ProcessorDerived::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 ProcessorDerived::HandleBuffer(BufferBase &buffer)
as follows:

...
#include <typeinfo>

class ProcessorDerived : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(BufferBase &buffer)
{
std::cout << "ProcessorDerived::HandleBuffer(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 interoperability 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 ProcessorDerived object gets called?
>
(My reasoning says that in both cases, HandleBuffer(BufferBase &buffer)
will be called, because the method is being invoked through a base
class pointer.)
The second virtual member function
void ProcessorDerived::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 ProcessorDerived::HandleBuffer(BufferBase &buffer)
as follows:

...
#include <typeinfo>

class ProcessorDerived : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(BufferBase &buffer)
{
std::cout << "ProcessorDerived::HandleBuffer(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(BufferBase &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 interoperability 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 ProcessorDerived : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(BufferBase &buffer)
{
std::cout << "ProcessorDerived::HandleBuffer(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(BufferBase &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, ProcessorDerived had two
methods:

HandleBuffer(BufferBase &buffer) // inherited from ProcessorBase
HandleBuffer(BufferDerived &buffer) // a new, overridden version in
ProcessorDerived

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 VideoFrameBuffer : 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(BufferBase &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 VideoFrameBuffer objects, or other objects
derived from BufferBase.

For example, if somehow an VideoFrameBuffer 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 ProcessorDerived : public ProcessorBase
{
// ...
public:
virtual void HandleBuffer(BufferBase &buffer)
{
std::cout << "ProcessorDerived::HandleBuffer(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(BufferBase &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, ProcessorDerived had two
methods:

HandleBuffer(BufferBase &buffer) // inherited from ProcessorBase
HandleBuffer(BufferDerived &buffer) // a new, overridden version in
ProcessorDerived

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 VideoFrameBuffer : 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(BufferBase &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 VideoFrameBuffer 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(BufferType &buffer) = 0;
};

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

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

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

AudioBuffer audiobuf;
AudioProcessor< audioproc;
audioproc.HandleBuffer( audiobuf );

// test
// audioproc.HandleBuffer( 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
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...
4
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...
4
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...
14
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
by: Daniel | last post by:
I have the following three classes class A { public: virtual void f() = 0; }; class B: public A {
3
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...
2
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...
12
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...
5
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,...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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...

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.