objective-c++: is it possible to define a c++ class with a method which returns objective-c classes and uses covariant returns? - objective-c++

**Edit: this only happens with llvm; gcc supports this just fine.
Consider the following.
Objective-c classes A and B.
B is a subclass of A.
We want a c++ hiearchy that looks like:
class X {
//...
public:
virtual A* getFoo();
};
class Y : public X {
//...
public:
B* getFoo();
};
However, if you do this, you'll get an error, as the Objective-c types confuse the c++ compiler:
error: virtual function 'getFoo' has a different return type ('Y *') than the function it overrides (which has return type 'X *')
I'm wondering if anyone has a workaround for this? (Obviously, long term, we'll be moving away from Objective-c classes, but that's not today).
P.S. This seems like the most similar question I could find, but I'm pretty sure it's a different problem.

This compiles and runs fine for me:
#import <Cocoa/Cocoa.h>
#interface A : NSObject
- (NSString*) bar;
#end
#implementation A
- (NSString*) bar
{
return #"";
}
#end
#interface B : A
#end
#implementation B
- (NSString*) bar
{
return #"!!!";
}
#end
class X {
//...
public:
virtual A* getFoo() = 0;
};
class Y : public X {
//...
public:
virtual B* getFoo() { return [B new]; }
};
int main (int argc, char const *argv[])
{
X* x = new Y;
NSLog(#"%#", [x->getFoo() bar]); // >> !!!
return 0;
}
Maybe your problem was that you didn't import B's header file into the file defining Y? You can't get covariance (in c++, at least) on incomplete classes, as the compiler needs to know that B inherits from A in order to compile Y.
Anyway, to answer your question, looks like it is possible to do this.

Related

C++ vector as member of Objective C class doesn't retain value

So I've got an Objective C class that will implement the NSTableViewDataSource protocol to display a list of audio output devices. I'm calling a C++ class that returns device information as a std::vector of C structs of the form
typedef struct DeviceInfo {
AudioDeviceID devID;
char name[128];
int nInputChannels;
int nOutputChannels;
} DeviceInfo;
The Objective C class is
#interface PreferencesViewController : NSObject <NSTableViewDataSource> {
AudioOutputController *audioOutputController_;
vector<DeviceInfo> audioOutputDevices_;
}
- (void)setAudioOutputController:(AudioOutputController *)controller;
- (void)updateDeviceList;
- (IBAction)buttonPressed:(id)sender;
#end
The main app controller sets the PreferencesViewController's AudioOutputController member (the C++ class), then calls updateDeviceList(), which tells the AudioOutputController to query the available audio devices and return a vector of DeviceInfo structs
- (void)updateDeviceList {
/* Update the list of currently connected devices and return device information */
audioOutputController_->setAvailableDevices();
audioOutputDevices_.clear();
audioOutputDevices_ = audioOutputController_->getAvailableDevices();
for (int i = 0; i < audioOutputDevices_.size(); i++) {
printf("Device %d: %s\n", i, audioOutputDevices_[i].name);
printf("\t%d Output Channels\n", audioOutputDevices_[i].nOutputChannels);
}
}
This all works completely fine and prints the available audio devices, but the vector of structs doesn't seem to retain its value outside updateDeviceList(), so I see an empty vector when I try to access it in the NSTableViewDataSource protocol methods. If I try to just print the size of the vector in an IBAction method, for example
- (IBAction)buttonPressed:(id)sender {
printf("audioOutputDevices_.size() = %lu\n", audioOutputDevices_.size());
}
it says the vector is empty. I'm new to combining C++ and Objective C, so any help is greatly appreciated.
Edit: something else peculiar. If I call PreferencesViewController's updateDeviceList() method from the AppDelegate's applicationDidFinishLaunching(), as follows:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
audioOutputController_ = new AudioOutputController();
preferences_ = [[PreferencesViewController alloc] init];
[preferences_ setAudioOutputController:audioOutputController_];
[preferences_ updateDeviceList:self];
}
#end
then I get the problem stated above, with the C++ vector not retaining its value. If I instead make updateDeviceList() an IBAction callback for an interface button, then when I call it it retains its value and the device information gets added to the table.
I believe (from a similar experience of mine) that during application startup the C++ constructor of vector<DeviceInfo> audioOutputDevices_ is somehow called again, which clears it.

Finding a on object in a vector by one of its values

The problem I encountered and am unable to solve goes something like this. I have two classes:
class1
{
private:
int identifier;
double value;
public:
setters,getters,etc...
}
class2
{
private:
vector<class1> objects;
vector<int> some_value;
vector<double> other_value;
...
}
The problem is I need to search through the vector of objects in an object of the second class by its identifier in the class1 object(from a member function of class2). I tried something like:
int getObj(const int &ident, double &returnedValue, double &returnedOther_value)
{
int p;
p = find(objects.begin()->getIdentifier(),objects.end()->getIdentifier(),ident);
..
.. and then i was hoping to find a way to return from the found iterator values of corresponding(non-const) member variables value and other_value from both classes, but the code so far does not compile, because I'm likely doing the search all wrong. Is there a way I could do this with the find(or any other algorithm) or should I stick to my previous working realization with no algorithms?
You need to use find_if with a custom predicate. Something like:
class HasIdentifier:public unary_function<class1, bool>
{
public:
HasIdentifier(int id) : m_id(id) { }
bool operator()(const class1& c)const
{
return (c.getIdentifier() == m_id);
}
private:
int m_id;
};
// Then, to find it:
vector<class1>::iterator itElem = find_if(objects.begin(), objects.end(), HasIdentifier(ident));
I haven't tested it, so maybe it needs some tweaking.
If you have C11, I guess you can use lambdas, but I don't have it, so I haven't had the chance to learn them.
UPDATE:
I've added an example in http://ideone.com/D1DWU

XCode compilation error for C++ code

I am trying to use my C++ classes for an iPhone app. I got 2 compilation errors in XCode that I do not quite understand. Here is the first one, in this header file myApps.h, I declare a class myApps and a struct PointF:
#pragma once
struct PointF {
float x;
float y;
}; // **compilation error message here :Multiple types in one declaration**
class myClass {
...
}
The second error is in a header file too,
#pragma once
class myClass1;
class myClass2;
class MyClass
{
public:
MyClass(void *view);
~MyClass();
virtual void Draw(myClass1 *c1);
//Error: Candidate is virtual void MyClass::Draw(myClass1 *)
virtual void Move(myClass2 c2[], myClass1 *c1, void *callback);
//Error: Candidate is virtual void MyClass::Move((myClass2, myClass1*, void*)
};
Thanks for your help
Ok, I don't know if this will help you but, from what I see:
myClass should have a semicolon at the end:
class myClass {
...
};
For the Candidate is virtual void MyClass::Draw(myClass1 *) below the last function of your class:
using myClass1::Draw;
using myClass1::Move;
since you probably have a method Draw and Move in myClass1... More on it here. It's hard to figure out exactly since I can't see the stuff in myClass1 and myClass2.
Just check Whether your file extension is .m or .mm for C++ files it must be .mm extension.

Implementing run time polymorphism and inheritence

What is the equivalent concept of interface in java in objective C. I want to create a interface and define some common variables and methods which will be shared by many classes inheriting from my interface. When any class outside want to use a child class it will get a reference object of my interface which will point to correct child class.
How to achieve this in Objective C?
An Objective C equivalent of Java interfaces is called "protocol".
A small intro can also be found here, and if you want a full reference, it's at Apple
In Objective-C, you can achieve this by making use of Protocols. A protocol is basically the precursor to an interface in Java, so most of the behavior should come naturally.
A protocol declaration looks like the following:
#protocol Foo
-(void) foo;
-(int) boo: (int) arg;
#end
It may be implemented by a class. In the following case, you would say MyClass conforms to the Foo protocol.
#interface MyClass <Foo>
{
}
#end
#implementation MyClass
-(void) foo {
//do something
}
-(int) boo: (int) arg {
//do something else
return arg;
}
#end
Finally, you can pass them around like this:
-(void) someMethod: (id<Foo>) arg;
If you need to be more specific about the object, they can also be used like this:
-(void) someMethod: (NSObject<Foo> *) arg;

How to make a ConstantList Class in Objective C

How to make a ConstantList class in Objective C of an application which could be accessible to all the classes who are using constants.
like in Actionscript we do:
public class ConstantList
{
public static const EVENT_CHANGE:String = "event_change";
}
Or what is the best approach to handle application constant.
Regards
Ranjan
You can use global constants, like the following:
//MyConstants.m
NSString * const EVENT_CHANGE = #"event_change";
// MyConstants.h
extern NSString* const EVENT_CHANGE;
Now include MyConstants.h header to your implementation file and you can use EVENT_CHANGE constant string in it
I would recommend Vladimir's approach.
Just for completeness: You can do it as a class like this:
#interface Constants : NSObject {
}
+ (NSString*)aConstantString;
#end
#implementation Constants
+ (NSString*)aConstantString {
return #"This is always the same and accessible from everywhere";
}
#end
You access the value like:
NSString* string = [Constants aConstantString];