BCA 2023 Object-Oriented Programming (C++) Past Paper PDF

Summary

This is a BCA third semester past paper from 2023, covering Object-Oriented Programming concepts in C++. The paper includes questions on encapsulation, the need for OOP, and comparisons with structured programming.

Full Transcript

2023 B.C.A. Third Semester First Paper (Object Oriented Programming Using C++) 1(a) What do you nen by encapsula on and how it is impdemented in C++? Ans: Encapsula on in C++: Encapsula on is one of the fundamental principles of Object-Oriented P...

2023 B.C.A. Third Semester First Paper (Object Oriented Programming Using C++) 1(a) What do you nen by encapsula on and how it is impdemented in C++? Ans: Encapsula on in C++: Encapsula on is one of the fundamental principles of Object-Oriented Programming (OOP). It refers to bundling the data (variables) and the methods (func ons) that operate on the data into a single unit called a class. Encapsula on helps in restric ng direct access to some of the object's components, thereby maintaining data integrity and security. Implementa on in C++: Encapsula on in C++ is implemented using access specifiers: 1. Private: Members declared as private are accessible only within the class in which they are defined. This restricts access to sensi ve data or implementa on details. 2. Protected: Members declared as protected are accessible within the class and its derived classes. 3. Public: Members declared as public are accessible from outside the class. (b) What is the need Of Object-Oriented Programrning paradigm? Ans: The Need for Object-Oriented Programming (OOP) Paradigm The Object-Oriented Programming (OOP) paradigm was introduced to address the limita ons of procedural programming and to provide a more efficient, modular, and reusable approach to so ware development. Here are the key reasons why OOP is needed: 1. Improved Code Reusability OOP allows developers to reuse code by crea ng reusable objects and classes. This reduces redundancy and saves development me. For example:  Classes and objects can be used in mul ple programs.  Features like inheritance enable the extension of exis ng func onality. 2. Modularity and Organiza on By grouping data and func ons into classes, OOP makes programs modular and be er organized. It is easier to locate, modify, and debug specific sec ons of code without affec ng the rest of the system. 3. Enhanced Data Security Encapsula on helps restrict direct access to cri cal data by exposing it only through controlled methods (se ers and ge ers). This reduces the risk of accidental or malicious manipula on of sensi ve data. 4. Real-World Problem Representa on OOP models real-world en es and their interac ons effec vely through objects. Concepts like inheritance and polymorphism make it easier to represent rela onships and behaviors in the problem domain. 5. Ease of Maintenance and Scalability Object-oriented programs are easier to maintain and extend. For example:  Adding new features is straigh orward by crea ng new classes or extending exis ng ones.  Polymorphism allows for flexible and dynamic behavior changes. 6. Support for Abstrac on OOP allows developers to focus on high-level designs while hiding implementa on details through abstrac on. This improves code clarity and reduces complexity. 7. Support for Collabora on OOP enables team-based development. Different developers can work on different classes or modules independently, improving produc vity and reducing conflicts. 2(a) Compare and contrast e structured programming and object-oriented gramming. Ans: Comparison Between Structured Programming and Object-Oriented Programming (OOP) Aspect Structured Programming Object-Oriented Programming (OOP) Procedural-based programming Object-based programming Paradigm paradigm. paradigm. Focuses on func ons and Focuses on objects that encapsulate Primary Focus procedures to operate on data. data and methods. Achieved by dividing programs into Achieved by organizing programs into Modularity func ons or procedures. classes and objects. Data is globally accessible and Data is encapsulated within objects Data Handling shared among func ons. and accessed through methods. Not supported; data and logic are Supported; data and methods are Encapsula on separate. bundled together in classes. Aspect Structured Programming Object-Oriented Programming (OOP) Limited abstrac on; Provides abstrac on by hiding Abstrac on implementa on details are implementa on details. exposed. Not supported; no direct way to Supported; allows code reuse Inheritance reuse code across procedures. through class inheritance. Supported; enables dynamic method Polymorphism Not supported. behavior. Code Limited reusability; func ons can High reusability through inheritance Reusability be reused but lack flexibility. and polymorphism. Low security; no mechanism to High security; encapsula on protects Security restrict access to data. data from unauthorized access. Suitable for simple, well-defined Suitable for complex and real-world Problem-Solving tasks. problems. Example C, Pascal, Fortran C++, Java, Python, C# Languages Key Differences 1. Data and Behavior: Structured programming separates data and behavior, while OOP combines them in objects. 2. Flexibility: OOP supports dynamic behavior through polymorphism, making it more flexible for evolving requirements. 3. Real-World Mapping: OOP can model real-world en es more effec vely using objects, whereas structured programming focuses on a step-by-step approach. (b) Explain Message Passing and Dynamic Binding. Ans: Message Passing Defini on: Message passing is a mechanism in Object-Oriented Programming (OOP) where objects communicate with each other by invoking methods. Instead of directly accessing the data or func onality of another object, an object sends a message (a method call) to another object, reques ng it to perform a specific ac on. How It Works: 1. An object sends a message (method call) to another object. 2. The receiving object executes the corresponding method, o en involving internal state changes or calcula ons. 3. The result may be returned to the calling object. Dynamic Binding Defini on: Dynamic binding (also known as late binding) is the process where the method to be invoked is determined at run me, not at compile me. It allows objects of derived classes to override methods of their base class and execute the appropriate version during program execu on. Key Concepts: 1. Achieved through virtual func ons in C++. 2. Enables polymorphism, allowing a single interface to work with mul ple types. 3. Provides flexibility, as the method executed depends on the type of the object being referenced. Key Differences: Aspect Message Passing Dynamic Binding Facilitates object-to-object Determines the method to invoke at Purpose communica on. run me. Happens explicitly through Happens implicitly during method Timing method calls. execu on. Rela on to Focuses on which method an object Focuses on how objects interact. Objects should execute. 3(a) Explain the term class and 0bJect. Ans: Class and Object in Object-Oriented Programming (OOP) Class A class is a blueprint or template for crea ng objects. It defines the structure and behavior that objects of the class will have. A class groups together data members (variables) and member func ons (methods) into a single unit.  Key Features: o Encapsula on: Combines data and methods. o Abstrac on: Hides implementa on details. o Can include constructors, destructors, and other specialized methods.  Key Features: o Objects are created from a class. o Each object has its own copy of the class's data members. o Objects interact by sending messages (method calls). Key Differences Between Class and Object Aspect Class Object Defini on A blueprint or template for objects. An instance of a class. Does not occupy memory un l objects are Existence Occupies memory when created. created. Used to represent real-world Purpose Used to define structure and behavior. en es. Example Car (concept). car1 (a specific Toyota car). (b) What are constructors? Explain copy constructor with suitable example. To Ans: Constructors in C++ Defini on: A constructor is a special member func on in C++ that is automa cally called when an object of a class is created. It is primarily used to ini alize the data members of a class. Key Features of Constructors: 1. Same Name as Class: The name of the constructor must match the class name. 2. No Return Type: Constructors do not have a return type (not even void). 3. Automa c Invoca on: They are called automa cally when an object is created. 4. Overloading: Mul ple constructors can be defined in the same class with different parameter lists (constructor overloading). Types of Constructors: 1. Default Constructor: Takes no arguments and ini alizes data members to default values. 2. Parameterized Constructor: Accepts parameters to ini alize data members with specific values. 3. Copy Constructor: Ini alizes a new object by copying the values of another object of the same class. Copy Constructor Defini on: A copy constructor is a special type of constructor that creates a new object as a copy of an exis ng object. It is invoked when: 1. An object is ini alized from another object of the same class. 2. An object is passed by value to a func on. 3. An object is returned by value from a func on. Key Features of the Copy Constructor: 1. Shallow Copy vs. Deep Copy: o Shallow Copy: The default copy constructor performs a shallow copy, which copies the values of all member variables. o Deep Copy: A custom copy constructor is required to handle deep copying for dynamically allocated memory. 2. When to Define a Custom Copy Constructor: o If the class contains pointers or dynamically allocated memory. o To ensure proper resource management and avoid issues like double dele on. 4(a) Write Short notes on : (i) C++ Garbage Collec on Ans:Defini on: Garbage collec on is the process of automa cally reclaiming unused memory to ensure efficient memory management. Unlike some programming languages like Java or Python, C++ does not have built-in garbage collec on. Instead, memory management is the responsibility of the programmer, typically through the use of manual techniques like new, delete, and smart pointers. Memory Management in C++: 1. Dynamic Alloca on: o Memory is allocated at run me using new or malloc. o Example: o int *ptr = new int(5); 2. Manual Dealloca on: o Memory must be explicitly deallocated using delete or free. o Example: o delete ptr; 3. Issues Without Garbage Collec on: o Memory Leaks: Occur if memory is allocated but not freed. o Dangling Pointers: Pointers that reference deleted memory. o Double Dele on: A emp ng to free the same memory twice. Alterna ves to Garbage Collec on in C++:  Smart Pointers (introduced in C++11): Automa cally manage memory by dealloca ng unused objects. o Examples: std::unique_ptr, std::shared_ptr, std::weak_ptr. o Example Usage: o #include o std::unique_ptr ptr = std::make_unique(10);  RAII (Resource Acquisi on Is Ini aliza on): Encapsulates resource management into objects. (ii) Abstract Classes Ans:Defini on: An abstract class in C++ is a class that serves as a blueprint for derived classes. It cannot be instan ated directly and typically contains at least one pure virtual func on. A pure virtual func on is declared by assigning = 0 to the func on prototype. Purpose: Abstract classes define a common interface for derived classes. They enforce that all derived classes must implement specific methods. Features of Abstract Classes: 1. They can have both pure virtual func ons and regular member func ons. 2. Objects of abstract classes cannot be created directly. 3. A derived class must override all pure virtual func ons to become concrete. Advantages of Abstract Classes: 1. Enforce Interface: Ensures derived classes follow a specific structure. 2. Code Reusability: Shared methods in the base class can be reused by derived classes. (b) Differen ate between nested if-else and switch statement. Ans: Difference Between Nested If-Else and Switch Statement Aspect Nested If-Else Switch Statement Used for complex, mul -condi on Used for simpler, mul -way branching Purpose decision-making. based on a single variable or expression. Involves mul ple if, else if, and Uses switch and case labels with break Syntax else blocks. statements. Can evaluate any type of condi on Only supports evalua ng a single Condi on (e.g., rela onal, logical, or variable or expression of integer, Type mul ple variables). character, or enum type. Be er for handling complex Complexity Ideal for straigh orward comparisons. condi ons. Can become difficult to read and Easier to read and maintain with clear Readability maintain if deeply nested. case labels. Directly jumps to the matching case, Evaluates condi ons sequen ally Execu on improving efficiency for large decision un l one is true. trees. Fall-Through No fall-through; only the matching Has fall-through behavior unless break Behavior block is executed. is used explicitly. Allows combining mul ple Limited to comparing a single variable Flexibility condi ons and logical opera ons. or expression to constant values. Handles discrete, predefined values for Example Handles general condi ons. decisions. When to Use? 1. Use Nested If-Else: o When the decision depends on complex condi ons. o When logical operators (&&, ||) are required. 2. Use Switch Statement: o When the decision depends on a single variable or expression. o For handling predefined, discrete cases like menu op ons or enums. 5(a) How ambiguity In mu lple Inhedtance can be resolved? Ans: Ambiguity in Mul ple Inheritance and How It Can Be Resolved What is Mul ple Inheritance? Mul ple inheritance occurs when a class inherits from more than one base class. In C++, a derived class can inherit features (data members and member func ons) from mul ple base classes. However, this can lead to ambiguity when mul ple base classes have methods with the same name or when the derived class doesn't know which base class to use. Ambiguity in Mul ple Inheritance Ambiguity arises when a derived class inherits the same member (func on or variable) from more than one base class. This can cause confusion as the compiler does not know which base class method or member to call. How to Resolve Ambiguity? There are several ways to resolve ambiguity in mul ple inheritance in C++: 1. Using Scope Resolu on Operator (::) You can explicitly specify which base class's func on you want to call using the scope resolu on operator (::). This resolves the ambiguity by directly referencing the method from the respec ve base class. 2. Virtual Inheritance When using virtual inheritance, the base classes are shared, and only one instance of the common base class is inherited by the derived class. This eliminates ambiguity by ensuring that the derived class has a single copy of the common base class. 3. Using virtual Keyword in Mul ple Inheritance In certain situa ons, making the base class methods virtual allows proper dispatch and can reduce ambiguity. This is especially useful if you have virtual func ons and need to ensure polymorphic behavior. (b) With suitable program in C++, explain operator overloading. Ans: Operator Overloading in C++ Defini on: Operator overloading in C++ allows you to define custom behavior for operators (like +, -, *, [], etc.) when they are applied to objects of user-defined classes. By overloading operators, you can make your classes more intui ve and easier to use in expressions that involve objects of those classes. Key Points About Operator Overloading: 1. Syntax: You define an operator func on with a special keyword operator followed by the operator symbol you want to overload. 2. Member and Non-Member Func ons: Operators can be overloaded as member func ons or non-member func ons (friend func ons). 3. Restric ons: o You cannot overload certain operators like ::, sizeof, and.. o You cannot change the precedence or associa vity of operators. Example of Operator Overloading: Let's create a simple class Complex that represents complex numbers and overload the + operator to add two complex numbers. Explana on: 1. Class Defini on: o The class Complex has two private data members: real and imag, which store the real and imaginary parts of the complex number, respec vely. o The constructor ini alizes the complex number with the given real and imaginary parts (default values are set to 0). 2. Overloading the + Operator: o The operator+ is overloaded to add two Complex objects. It returns a new Complex object where the real parts and imaginary parts are added separately. o We use the const Complex &other parameter to ensure that the argument passed is not modified. 3. Displaying the Result: o The display func on is used to print the complex number in the format real + imag i. 4. Main Func on: o Two Complex objects num1 and num2 are created with ini al values. o The overloaded + operator is used to add num1 and num2, and the result is stored in result. o The result is then displayed using the display method. Explana on of the Key Concepts: 1. Operator Func on: The operator+ func on is defined as a member func on of the Complex class. This allows you to directly add two objects of the Complex class using the + operator. The func on returns a new Complex object that represents the sum of the two complex numbers. 2. Returning a New Object: The overloaded + operator creates a new Complex object that contains the sum of the real and imaginary parts of the two complex numbers. 3. Use of const: The argument const Complex &other ensures that the func on does not modify the original Complex object passed to it. It also avoids unnecessary copying of the object. 6(a) What is the use of ‘this' keyword in Ans: Use of the this Keyword in C++ In C++, the this keyword is a special pointer that is automa cally passed to all non-sta c member func ons of a class. It points to the current instance of the class (i.e., the object that invoked the member func on). Key Uses of the this Keyword: 1. Referring to the Current Object: o this is a pointer to the current object within the member func on. It helps differen ate between class members and parameters or local variables that might have the same name. 2. Accessing Member Variables and Func ons: o You can use this to explicitly access member variables and func ons of the class, though it is usually not necessary as C++ allows direct access to them. 3. Checking for Self-Assignment (in Assignment Operators): o The this pointer can be used to check for self-assignment in the assignment operator. This prevents the object from assigning its own values to itself (which could lead to issues like memory corrup on in some cases). (b) Discuss the use of public, private, and protected access specifiers and their visibility in the class. Ans: Access Specifiers in C++: public, private, and protected In C++, access specifiers are used to define the accessibility (visibility) of class members (variables and methods) from outside the class. The three main access specifiers are public, private, and protected. Each has its own level of visibility and control over access to class members. 1. Public Access Specifier (public)  Visibility: Members declared as public are accessible from anywhere, both inside and outside the class.  Usage: Public members are typically used for func ons that need to be accessed by other parts of the program, such as the class's interface methods.  Common Examples: Methods that provide access to or modify the data members of the class.  Explana on: In this example, both the x variable and the methods setX() and display() are public. This allows access to these members directly from outside the class, such as in main(). 2. Private Access Specifier (private)  Visibility: Members declared as private are accessible only within the class or by friend func ons (func ons or other classes that are declared as friends). They are not accessible directly from outside the class.  Usage: Private members are typically used to represent data that should be hidden or protected from external modifica on, ensuring data encapsula on and integrity.  Common Examples: Internal data members and helper func ons that should not be exposed directly. 3. Protected Access Specifier (protected)  Visibility: Members declared as protected are accessible within the class and in derived classes (i.e., subclasses), but not from outside the class.  Usage: Protected members are typically used in base classes where you want to allow derived classes to access certain members, but you want to prevent external access to those members.  Common Examples: Member variables that need to be inherited and used by derived classes but should not be accessed directly from outside the class. Summary of Visibility Access Visibility Specifier Public Accessible from anywhere (inside and outside the class). Private Accessible only within the class or by friend func ons. Accessible within the class and by derived classes (but not outside the Protected class). When to Use Each Access Specifier: 1. Public: o Use when the member needs to be accessed by external code, such as ge er and se er methods, or when the func on is part of the class's public interface. 2. Private: o Use for data members and func ons that are meant to be hidden from the outside world. The principle of encapsula on encourages keeping implementa on details private and only exposing essen al func onality. 3. Protected: o Use when the member needs to be accessed by derived classes (for inheritance) but should not be accessible from outside the class. (c) What do you mean by aggrega on? Ans: Aggrega on in Object-Oriented Programming (OOP) Aggrega on is a concept in object-oriented programming that represents a "has-a" rela onship between two objects, where one object is a part of another but can exist independently. It is a form of associa on that allows a class to contain references to other objects. Unlike composi on (which is a stronger form of associa on), aggrega on represents a looser rela onship where the life me of the contained objects does not depend on the life me of the container object. Key Characteris cs of Aggrega on: 1. "Has-a" Rela onship: In aggrega on, one object "has" or "contains" another object, but the contained object can exist independently of the container object. 2. Independent Life me: The life me of the aggregated object is independent of the life me of the object that aggregates it. If the container object is destroyed, the aggregated object can s ll exist. 3. Weak Ownership: Aggrega on signifies a weak rela onship between the container and the contained objects. The contained object can exist on its own outside of the aggrega on context. Explana on:  Aggrega on Rela onship: The Department class contains a collec on of Employee objects, meaning a department has employees. However, the Employee objects can exist independently of the Department.  Independence: The Employee objects emp1 and emp2 are not owned by the Department class. They could be part of mul ple departments or even exist without any department.  Weak Ownership: If the Department object is destroyed, the Employee objects do not get destroyed, which signifies the weak ownership or aggrega on rela onship. Comparison with Composi on:  Aggrega on: The objects involved in aggrega on can exist independently. For example, an Employee can exist without a Department, and a Department can exist without any Employee.  Composi on: In composi on, the contained object cannot exist independently of the container object. For example, a House class may have a Room class as a member, and if the House is destroyed, the Room is destroyed as well. 7(a) With suitable example differen ate between overloading and overriding. Ans: Difference Between Overloading and Overriding in C++ Both overloading and overriding are concepts in object-oriented programming that deal with mul ple func ons or methods having the same name but with different behaviors. However, they differ significantly in their purpose, usage, and the way they are handled in C++. Let's break down both concepts: 1. Func on Overloading (Compile-Time Polymorphism)  Defini on: Overloading occurs when two or more func ons in the same scope (same class) have the same name but differ in the number or type of their parameters. The return type can be the same or different, but the func on signatures (i.e., the number and/or type of parameters) must be different.  Key Points: o It is resolved at compile me. o It happens within the same class. o Overloading is based on the number or types of parameters.  Explana on: In this example, the func on print is overloaded with different parameter types (int, double, string). The appropriate version of the func on is chosen based on the type of the argument passed. 2. Func on Overriding (Run-Time Polymorphism)  Defini on: Overriding occurs when a subclass (derived class) provides its own implementa on of a func on that is already defined in its superclass (base class). The func on signature in the derived class must be the same as in the base class.  Key Points: o It is resolved at run me. o The func on in the derived class overrides the func on in the base class. o Overriding allows a derived class to modify or extend the behavior of a base class func on. o The virtual keyword is typically used in the base class to enable func on overriding in C++.  Explana on: In this example, the sound func on is overridden in the derived classes Dog and Cat. Although the sound func on exists in the base class Animal, the appropriate func on for each derived class (Dog or Cat) is called at run me, demonstra ng run me polymorphism. Key Differences Between Overloading and Overriding: Feature Overloading Overriding Same func on name with Same func on name with the same Defini on different parameters parameters but in derived class Resolu on Resolved at compile me Resolved at run me (dynamic dispatch) To perform similar opera ons with To modify or extend the func onality of Purpose different arguments an inherited func on Func on Different parameter types or Same func on signature (name, return Signature number type, and parameters) Requires inheritance (base and derived Inheritance Does not require inheritance class) Requires virtual keyword in the base Use of virtual Not required class to enable overriding Example void print(int); void print(double); void sound() override; (b) What is inheritance? Explain run me polymorphism. Ans: Inheritance in C++ Inheritance is one of the core concepts of Object-Oriented Programming (OOP). It allows a class (called the derived class) to acquire the proper es and behaviors (data members and member func ons) of another class (called the base class). Through inheritance, a derived class can extend or modify the func onality of the base class, enabling code reusability and enhancing the organiza on of complex programs. Key Points of Inheritance: 1. Base Class: The class whose proper es and behaviors are inherited by another class. 2. Derived Class: The class that inherits the proper es and behaviors from the base class. 3. Access Specifiers in Inheritance: The access to inherited members of the base class depends on the access specifiers used in the inheritance declara on: o Public inheritance: Public and protected members of the base class are accessible in the derived class. o Private inheritance: All members of the base class become private in the derived class. o Protected inheritance: Public and protected members of the base class are inherited as protected in the derived class. Types of Inheritance:  Single Inheritance: A derived class inherits from one base class.  Mul ple Inheritance: A derived class inherits from more than one base class.  Mul level Inheritance: A class derives from another class, which itself is derived from another class.  Hierarchical Inheritance: Mul ple derived classes inherit from a single base class.  Hybrid Inheritance: A combina on of mul ple types of inheritance.  Explana on: The Dog class inherits the eat func on from the Animal class. The derived class Dog can access both its own methods (like bark()) and the inherited methods (like eat()). Run-Time Polymorphism (Dynamic Polymorphism) Run- me polymorphism (also known as dynamic polymorphism) is a feature in C++ where a func on call to an overridden func on is resolved at run me, depending on the type of object being referred to by the base class pointer or reference. This is typically achieved through func on overriding and involves the use of the virtual keyword. Key Points of Run-Time Polymorphism: 1. Func on Overriding: The derived class provides its own implementa on of a func on that is already defined in the base class. 2. Virtual Func ons: The base class func on must be declared as virtual to enable run me polymorphism. This allows the compiler to use the correct func on from the derived class when using a base class pointer or reference. 3. Base Class Pointer/Reference: A pointer or reference to the base class can point to an object of the derived class, enabling dynamic method dispatch. How it Works:  When a base class pointer or reference is used to call a method, the func on that gets executed is the one that corresponds to the actual object type (derived class) rather than the base class type.  The decision about which method to call is made at run me based on the object type.  Explana on: o The func on sound() is virtual in the base class Animal. o The Dog and Cat classes override this method. o Even though animal1 and animal2 are pointers of type Animal, they point to objects of type Dog and Cat respec vely. o At run me, the correct version of sound() (either Dog or Cat) is called, based on the actual type of the object the base class pointer is poin ng to. Benefits of Run-Time Polymorphism: 1. Flexibility: It allows the program to select the appropriate method at run me, making the program more flexible and adaptable. 2. Code Reusability: By overriding func ons, derived classes can reuse the code from the base class and modify it to suit their needs. 3. Dynamic Behavior: You can create more dynamic and complex systems, such as handling mul ple types of objects through a common interface. 8(a) What are the file streams? Ans: File Streams in C++ In C++, file streams are used to handle reading from and wri ng to files. A file stream represents an object that is used to perform input and output opera ons on files. Streams provide an abstrac on that allows the program to read from and write to files in a manner similar to how data is read and wri en from/to the standard input/output devices (such as the console). There are three types of file streams in C++: 1. Input File Stream (ifstream): o Used to read data from a file. o It provides func ons to open, close, and read data from files. 2. Output File Stream (ofstream): o Used to write data to a file. o It provides func ons to open, close, and write data to files. 3. File Stream (fstream): o Used for both reading from and wri ng to files. o It is a combina on of ifstream and ofstream and allows reading from and wri ng to the same file. Each of these streams provides func ons to open a file, check if the file was opened successfully, read data from the file (in the case of input file streams), or write data to the file (in the case of output file streams). File Stream Opera ons:  Opening a File: The file must be opened before performing any opera ons. The open() func on is used to open a file.  Reading from a File: The ifstream or fstream stream can be used to read data from a file using the extrac on operator (>>) or the getline() func on.  Wri ng to a File: The ofstream or fstream stream can be used to write data to a file using the inser on operator (

Use Quizgecko on...
Browser
Browser