Comparison of Swift and C++ inheritance, generics vs templates, structures vs classes, parameter passing. Differences between Swift and C++ that might surprise a C++ programmer.
HOME
Swift Pitfalls for C++ Programmers
November 10, 2015
Here are some surprising differences between Swift and C++ when it comes to object oriented programming in the two languages. If you are a C++ programmer interested in Swift, read on.
A Different Access Control Paradigm
Declaring a class member private won't neccessarily prevent derived classes from accessing it. That's because Swift uses an access control paradigm that is different from the one used in C++, Java, and Objective C. Please see this Apple documentation for more details.
Struct, Class, and Parameter Passing
Struct vs. Class
- A struct cannot be derived from another struct or from a class, but can implement a protocol.
- A struct has value semantics, class has reference semantics. Behavior of structs may appear strange to a C++ programmer. For example:
// S is a struct, C is a class. Both have a property named m_Int.
var s : S = S() // have to use var here
s.m_Int = 123
let s1 : S = s
s.m_Int = 1230 // s1.m_Int is still 123
let c : C = C() // let is OK here
c.m_Int = 321
let c1 : C = c
c.m_Int = 3210 // c1.m_Int is 3210, c and c1 point/refer to the same object
Passing Struct and Class as Function Parameters
Passed as parameters, classes and structures behave consistently with their semantics, reference and value, respectively. The compiler won't let you use them in ways violating the semantics, which is a nice safety feature. However, there is an interesting use of the var and inout keywords with parameters.
- If passed as a regular parameter, a struct cannot be modified in a function.
- If passed as a regular parameter, a class can be modified, but another object can't be assigned to the parameter.
- If the parameter is declared as var, then:
- If it's of a class type, it can be assigned a different class instance, but the assignment won't survive after the call returns.
- If it's of a struct type, it can be modified, but the changes won't be visible after the return.
- If the parameter is declared as inout, the behavior is similar to var, i.e. changes can be made inside the function, but those changes survive upon returning from the function. Please note that you need to use & with inout arguments, just as if you were passing a pointer in C++.
No Pure Virtual Functions
There are no pure virtual functions in Swift. One has to emulate them by using protocols and extensions. See
this Stack Overflow article.
Different Generics Behavior
Swift generics seem to be stricter than C++ templates. For example, the following C++ code compiles fine:
class A
{
public:
void change( int i ) { m_Int = i; }
private:
int m_Int;
};
template<typename T>
T changeObject( T x ) { x.change( 123 ); return x; }
int main()
{
A a;
A a1 = changeObject( a );
return 0;
}
However, if we try similar Swift code, this won't compile:
class A
{
func change( _i : Int ) -> Void
{
myInt += _i;
}
var myInt = 0
}
func changeObject<T>( x : T) ->T
{
x.change( 3 ) // The compiler says: Value of type 'T' has no member 'change'
return x
}
var a: A = A()
a = changeObject(a)
This can, however, be fixed easily by introducing a protocol, using an extension to make A implement it, and specifying that the template parameter implements the protocol:
protocol MyChangeable
{
func change( _i : Int) ->Void
}
extension A : MyChangeable{}
func changeObject<T : MyChangeable>( x : T ) ->T
{
...
Please feel free to contact me with questions or comments.
© 2015 swiftprogrammer.infoAnatoli Peredera